• 診断項目 No.39/127
  • Cookie・セッション管理
  • 重大度 中(medium)

Cookieの有効期間が過度に長くないか?Max-Age・Expiresの決め方・400日上限・診断基準

Cookieの有効期間が過度に長くないかは、Max-AgeやExpiresが1年を超えていないかで確認します。永続Cookieのリスク、Max-Age優先の規則、ブラウザの400日上限、用途別の目安、PHP・nginx・IIS・Next.jsの設定例を解説します。

結論(Cookieの有効期間が過度に長くない)

Cookieの有効期間が過度に長くないとは、サーバーが発行するCookieのMax-AgeやExpiresに、用途に必要以上の長い期限(この診断では1年超)が設定されていない状態です。期限の長い永続Cookieは共用パソコンや貸与端末、盗難端末に長く残り、その間ずっと悪用の機会を与えます。認証に関わるセッションIDは期限を付けないセッションCookieとし、サーバー側のタイムアウトで管理するのが原則です。

この記事のポイント

  • Max-AgeとExpiresの両方がある場合はMax-Ageが優先され、どちらも無いCookieはブラウザ終了で消えるセッションCookieです。
  • rfc6265bisはブラウザ側の有効期間の上限を400日以下と定め、ChromeはM104(2022年8月)から400日に切り詰めています。
  • ログインセッションは期限なし+サーバー側タイムアウト、表示設定は数か月程度が目安です。
  • 診断では失効まで1年(31,536,000秒)を超えるCookieが1件でもあれば△(重み2×0.45)です。
  • Cookieの期限より、サーバー側のセッション失効(アイドル・絶対タイムアウト)が本質です。
診断項目名Cookieの有効期間が過度に長くない
項目IDcookie.lifetime
分類Cookie・セッション管理
重大度・配点の重み中(medium) 重み 2
関連する標準・ガイドラインIPA「安全なウェブサイトの作り方」1.4 セッション管理の不備 4-(vi)(セッションIDをCookieにセットする場合の有効期限)/OWASP Session Management Cheat Sheet(非永続Cookieの推奨)/OWASP WSTG-SESS-02/draft-ietf-httpbis-rfc6265bis 5.5(有効期間の上限:400日以下)/CWE-539(Use of Persistent Cookies Containing Sensitive Information)

Cookieの有効期間が過度に長くないとは

Cookieの有効期間が過度に長くないとは、サーバーが発行するCookieに、1年を超える有効期間(Max-Age または Expires)が設定されていない状態です。セキュリティAIチェッカーはこの項目で、用途に必要以上に長く端末へ残るCookieがないかを確認します。

Set-Cookie: fontsize=large; Max-Age=7776000; Path=/; Secure; SameSite=Lax

Cookieには、ブラウザを閉じると消える「セッションCookie(非永続Cookie)」と、指定した期限まで端末に残り続ける「永続Cookie」があります。期限の長い永続Cookieは、共用パソコン・貸与端末・盗難端末などに長く残り、その間ずっと悪用の機会を与えます。セッションIDのような認証に関わる値ならなおさらです。

IPAは保険的対策として「セッションIDをCookieにセットする場合、有効期限の設定に注意する」(4-(vi))を挙げ、OWASP Session Management Cheat Sheet は、認証セッションには非永続Cookieを使うことを推奨しています。

Cookieの有効期間はどう決まるか(Max-AgeとExpires)

有効期間を決める2つの属性

属性書式意味
Max-Age秒数(例:Max-Age=86400)受信時刻からの秒数。0以下なら即時失効
ExpiresHTTP日付(例:Expires=Wed, 21 Oct 2026 07:28:00 GMT)失効する日時

両方が指定されている場合は Max-Age が優先 されます(rfc6265bis 4.1.2.2、MDNも同旨)。どちらも無いCookieはセッションCookieで、ブラウザのセッション終了時に削除されます。ただし、ブラウザの「前回のタブを復元」機能などでセッションCookieが残る場合があります。

期限の指定方法による違い

Expires は「日時」で指定するため、サーバーの時計が狂っていると意図しない期限になります。Max-Age は受信時刻からの秒数なので、サーバーとクライアントの時刻のずれに影響されません。新規実装では Max-Age の利用が扱いやすく、互換性のために両方を併記する実装も一般的です(その場合も Max-Age が優先されます)。

ブラウザ側の上限(400日)

改訂版Cookie仕様(rfc6265bis 5.5)は、ブラウザが Expires・Max-Age による有効期間に上限を設けなければならず、その上限は400日(34,560,000秒)を超えるべきでない、と定めています。Chrome は M104(2022年8月)からこの上限を実装しており、400日を超える期限は拒否されるのではなく400日に切り詰められます。Chromeの解説によれば、400日は「年1回程度訪れるサイトでもCookieが残る」ように13か月強として選ばれた値です。

このため「10年」などの期限を指定しても、少なくともChromeでは実際には約13か月で切れます。一方で、古いブラウザなど上限を実装していない環境では指定どおり長期間残ります。いずれにしても、長い期限を指定する意味は乏しく、用途に必要な最短の期間にするのが原則です。

Cookieの有効期間の目安(用途別)

用途推奨される有効期間の考え方
ログインセッションセッションCookie(期限なし)+サーバー側でアイドル・絶対タイムアウト
「ログイン状態を保持」数日〜数週間程度。サーバー側で失効・再認証を管理
文字サイズ・表示設定数か月程度で十分なことが多い
同意記録(Cookieバナー)法令・ガイドラインと運用方針に従う

Cookieの有効期間についてよくある誤解

  • 「Cookieの期限=セッションの有効期間」:Cookieが残っていても、サーバー側でセッションが失効していれば使えません。逆に、Cookieの期限を短くしてもサーバー側のセッションが無期限なら、盗まれたIDは使い続けられます。サーバー側のタイムアウト設定が本質です。
  • 「期限の長さはセキュリティと無関係」:端末に長く残る識別子は、端末の共用・紛失時の悪用、追跡、漏えい時の影響期間の拡大につながります。

Cookieの有効期間が過度に長くないの診断基準(セキュリティAIチェッカー)

取得方法

  1. トップページ(転送後の最終応答)と、トップページの同一オリジンリンクから選んだ最大4ページ(ログイン・管理・マイページ系を優先)を GETのみ で取得し、各最終応答の Set-Cookie を収集します(転送途中の応答のCookieは観測しません)。
  2. 各Cookieの失効時刻を次の順で求めます。
    • Max-Age があれば「診断時刻+Max-Age秒」(Expires より優先)
    • なければ Expires の日付を解釈した時刻
    • どちらも無い(または解釈できない)場合はセッションCookie扱い
  3. 失効時刻が診断時刻以前のもの(削除用のSet-Cookie)は判定から除外します。
  4. 有効なCookieが0件なら対象外(na)です。

判定条件

判定条件得点への影響
○ 問題なし(pass)失効時刻が診断時刻から1年(31,536,000秒)を超えるCookieが無い(セッションCookieのみの場合を含む)重み2 × 1.00
△ 要確認(warn)失効時刻が診断時刻から1年を超えるCookieが1件以上ある重み2 × 0.45
対象外(na)有効なCookieを観測できなかった(結果には重大度medium・重み2のまま記録)得点計算から除外
× 要改善(fail)使用しません―
  • 閾値の1年は、仕様上のブラウザ上限(400日)より短く、「用途に必要な最短の期間」から明らかに外れた設定を拾うための目安です。
  • 個々のCookieの用途(セッションか表示設定か)は公開情報から判断できないため、×ではなく△としています。△の場合は、該当Cookieが認証に関わるものかどうかを確認してください。
  • 根拠欄には「1年を超える有効期間(Max-AgeまたはExpires)を持つCookieがあります。」のように表示します。

自治体サイトでの判定例

観測したSet-Cookie判定
PHPSESSID=…; path=/; secure; HttpOnly(期限なし)○
fontsize=large; Max-Age=7776000; Path=/(90日)○
lang=ja; Expires=Fri, 31 Dec 2037 23:59:59 GMT; Path=/△
remember=…; Max-Age=315360000(10年)△
x=deleted; Expires=Thu, 01-Jan-1970 00:00:01 GMT のみ対象外(削除用のため除外)

Cookieの有効期間が長すぎるとどんなリスクがあるか

  • 共用端末での乗っ取り:図書館・公民館・窓口の共用パソコンで、長期の「ログイン保持」Cookieが残ると、次の利用者が前の利用者の電子申請や予約の画面にアクセスできてしまいます。
  • 漏えい時の影響期間の拡大:マルウェアやバックアップ経由でCookieが流出した場合、期限が長いほど悪用可能な期間が長くなります(CWE-539)。
  • プライバシー上の懸念:長期の識別子は利用者の継続的な追跡に使える情報となり、自治体サイトとして説明責任が生じます。

Cookieの有効期間の設定方法(PHP・Apache・nginx・IIS・Next.js)

PHP

<?php
// セッションCookieは期限なし(ブラウザ終了で削除)
// php.ini / .user.ini
// session.cookie_lifetime = 0
// session.gc_maxlifetime = 1440   ; サーバー側のセッション保持(秒)

// 表示設定用Cookieは必要最小限の期間(例:90日)
setcookie('fontsize', 'large', [
    'expires'  => time() + 60 * 60 * 24 * 90,
    'path'     => '/',
    'secure'   => true,
    'httponly' => false,  // JavaScriptで読む用途
    'samesite' => 'Lax',
]);

session.gc_maxlifetime はガベージコレクションの目安であり、厳密なタイムアウトにはアプリケーション側で最終アクセス時刻を記録して判定します。

Apache(固定Cookieを発行している場合)

mod_headers で Set-Cookie を出している設定があれば、Max-Age を見直します。Header set は同じ内部表にある他の Set-Cookie(アプリケーションのセッションCookie等)を置き換えて消してしまうため、add を使います。

Header always add Set-Cookie "notice_ver=1; Max-Age=7776000; Path=/; Secure; SameSite=Lax"

nginx(userid モジュール等)

userid         on;
userid_name    uid;
userid_expires 90d;   # max は避ける
userid_flags   secure samesite=lax;  # nginx 1.19.3以降

IIS(ASP.NET)

<system.web>
  <sessionState timeout="20" />
  <authentication mode="Forms">
    <forms timeout="30" slidingExpiration="true" requireSSL="true" />
  </authentication>
</system.web>

Next.js(Vercel)

import { cookies } from "next/headers";

// セッション:maxAge を指定しない(セッションCookie)
(await cookies()).set("session", token, { httpOnly: true, secure: true, sameSite: "lax", path: "/" });
// 表示設定:90日
(await cookies()).set("theme", "dark", { maxAge: 60 * 60 * 24 * 90, secure: true, sameSite: "lax", path: "/" });

段階的な導入と注意点

  1. 発行Cookieの一覧(名前・用途・期限)を作成します。
  2. 認証関連はセッションCookie化し、サーバー側のアイドルタイムアウトと絶対タイムアウトを設定します。
  3. 「ログイン状態を保持」機能がある場合は、期限を短くし、重要操作の前に再認証を求めます。
  4. 期限を短くすると、既存利用者の設定(文字サイズ等)がリセットされることがあります。告知のうえで切り替えます。
  5. 確認します。
curl -sSI https://www.city.example.lg.jp/ | grep -i '^set-cookie' | grep -Ei 'max-age|expires'

期限以外のCookie属性は、「CookieのSecure属性」、「CookieのHttpOnly属性」、「CookieのSameSite属性」、送信範囲は「CookieのDomain/Path範囲」の各ページで解説しています。

よくある質問(FAQ)

Cookieの有効期間はどのくらいが適切ですか?

用途に必要な最短の期間にするのが原則です。ログインセッションは期限なしのセッションCookieにしてサーバー側でタイムアウトを管理し、「ログイン状態を保持」は数日〜数週間程度、文字サイズなどの表示設定は数か月程度で十分なことが多いです。

Max-AgeとExpiresはどちらを使えばよいですか?

両方ある場合はMax-Ageが優先されます。Expiresは日時で指定するためサーバーの時計がずれると期限も狂いますが、Max-Ageは受信時刻からの秒数なので時刻のずれに影響されません。新規実装ではMax-Ageが扱いやすく、互換性のため両方を併記する実装も一般的です。

Cookieに10年の期限を付けるとどうなりますか?

rfc6265bisはブラウザに400日以下の上限を設けるよう定めており、ChromeはM104(2022年8月)から400日を超える期限を400日に切り詰めます。一方、上限を実装していない古いブラウザでは指定どおり長期間残るため、長い期限を指定する意味は乏しいといえます。

Cookieの期限を短くすれば、盗まれたセッションIDは使えなくなりますか?

Cookieの期限だけでは不十分です。サーバー側のセッションが無期限なら、盗まれたIDは使い続けられます。逆にCookieが残っていても、サーバー側でセッションが失効していれば使えません。サーバー側のタイムアウト設定が本質です。

セキュリティAIチェッカーで1年を超えるCookieがあると、どう判定されますか?

「△ 要確認」(重み2×0.45)です。個々のCookieの用途は公開情報から判断できないため×にはしていません。該当Cookieが認証に関わるものかどうかを確認してください。削除用のSet-Cookieは判定から除外します。

期限を短くすると利用者に影響はありますか?

既存利用者の文字サイズなどの設定がリセットされることがあります。発行しているCookieの一覧を作り、告知のうえで切り替えてください。

セキュリティAIチェッカーを利用する

この項目を含む127項目を、URLを入れるだけで無料診断します。

参考資料