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

Cookie名・値のサイズ上限とは?4096バイトの数え方・超過時の挙動・診断基準

Cookie名・値のサイズ上限は「名前+値の合計4096バイト」です。超えたCookieは黙って無視されます。バイト数の数え方、6265bisとASVSの根拠、PHP・Next.jsでの対策、確認方法と診断基準を解説します。

結論(Cookie名・値のサイズ上限)

Cookie名・値のサイズ上限とは、1つのCookieの「名前」と「値」の長さの合計を4096バイト(オクテット)以下にしなければならないという制限です。Cookie仕様の改訂版(draft-ietf-httpbis-rfc6265bis)は合計が4096オクテットを超えるSet-Cookieを丸ごと無視すると定め、OWASP ASVS 5.0.0 V3.3.5も同じ上限を求めています。超過したCookieは切り詰められず、エラーも出ずに捨てられます。

この記事のポイント

  • 上限は「名前+値」の合計4096バイトで、区切りの「=」と属性は含みません。
  • 数えるのは文字数ではなくバイト数で、UTF-8の日本語は1文字3バイトです。
  • 超過したCookieは切り詰めではなく全体が無視され、ログイン保持やCSRFトークンの不具合を招きます。
  • Cookieには識別子だけを入れ、データ本体はサーバー側セッションに置くのが根本対策です。
  • セキュリティAIチェッカーは、観測した全Cookieが4096バイト以下なら○、1件でも超えれば×と判定します。
診断項目名Cookie名・値のサイズ上限
項目IDcookie.size-limit
分類Cookie・セッション管理
重大度・配点の重み中(medium) 重み 2
関連する標準・ガイドラインOWASP ASVS 5.0.0 V3.3.5(Level 3:Cookie名と値の合計が4096バイトを超えない)/draft-ietf-httpbis-rfc6265bis §5.6・§5.7・§6.1/OWASP WSTG-SESS-02(Testing for Cookies Attributes)

Cookie名・値のサイズ上限とは

Cookie名・値のサイズ上限とは、1つのCookieの「名前」と「値」の長さの合計を 4096バイト(オクテット)以下 にしなければならないという制限です。

Set-Cookie: sid=3f9a1c...; Path=/; Secure; HttpOnly; SameSite=Lax
           └名前┘└値┘ ← この2つの合計が4096バイト以下

ブラウザが保存できるCookieの大きさには上限があります。Cookie仕様の改訂版(draft-ietf-httpbis-rfc6265bis、以下6265bis)は、Set-Cookie の解析手順の中で「名前文字列と値文字列の長さの合計が4096オクテットを超えたら、そのSet-Cookieを丸ごと無視する」と定めています。OWASP ASVS 5.0.0 の要件3.3.5も「アプリケーションがCookieを書き込むとき、Cookie名と値の合計が4096バイトを超えないこと。大きすぎるCookieはブラウザに保存されない」と規定しています。

上限を超えたCookieは、エラー表示もなく黙って捨てられます。その結果、ログイン状態が保持されない、CSRFトークンが届かない、同意バナーが何度も表示されるといった不具合が起き、開発者は原因を特定しにくくなります。セキュリティAIチェッカーのこの項目は、診断で観測したすべての Set-Cookie について、名前と値のバイト数の合計が4096を超えていないかを確認します。

Cookieのサイズ上限は仕様でどう決まっているか

6265bisの規定

節内容
§5.6(Set-Cookieヘッダーの解析)名前と値の長さの合計が4096オクテットを超える場合、アルゴリズムを中止し、そのset-cookie-stringを完全に無視する
§5.6(属性の解析)属性値が1024オクテットを超える場合、その属性(cookie-av)を無視する
§5.7(保存モデル)Cookie名と値の合計が4096オクテットを超える場合はCookie全体を無視する。Domain属性・Path属性も1024オクテット以下のものだけを扱う
§6.1(制限)ユーザーエージェントは少なくとも「1ドメインあたり50個」「合計3000個」のCookieを保存できることが望ましい(SHOULD)

「長さ」はバイト数で数える

ここでの「長さ」はオクテット(バイト)数です。UTF-8で日本語を直接入れると1文字が3バイトになるため、文字数ではなくバイト数で数える必要があります。仕様は区切りの = を名前・値に含めていないため、name=value の文字列から = を除いた「名前+値」で計算します。

値の例文字数バイト数(UTF-8)
abc12366
申請中(日本語を直接)39
1,400文字の日本語1,4004,200(上限超過)

属性が上限に含まれない理由

旧RFC 6265 §6.1は、最低限の保存能力を「名前・値・属性の合計で1Cookieあたり4096バイト以上」と定めていただけで、超過時の扱いはブラウザ実装により差がありました。6265bisは、名前+値(4096オクテット)と各属性値(1024オクテット)を別々に制限する形で整理しています。6265bisは2026年10月時点でRFC発行待ち(RFC Editorの最終確認段階)で、発行後はRFC 6265を置き換えます。

名前のないCookie

6265bisでは、= を含まない Set-Cookie: abc のような文字列は「名前が空、値が abc」として解釈されます。本診断もこの解釈に合わせて計算します。

関連する別の上限

  • リクエストヘッダー全体の上限:Cookieが多数あると、ブラウザが送る Cookie ヘッダーが大きくなり、サーバー側のヘッダーサイズ上限(ApacheのLimitRequestFieldSize既定8190バイト、nginxのlarge_client_header_buffers既定8KBなど)を超えて「400 Bad Request」や「431 Request Header Fields Too Large」になります。個々のCookieが4096バイト以下でも、合計で問題になる場合があります。
  • Partitioned Cookie:Chromeは1パーティションあたり最大180個、かつ埋め込みサイトごとに10KBまでとしています。Partitioned属性の要件は「Partitioned Cookieの要件」で確認します。

Cookieのサイズについてよくある誤解

  • 「4096文字まで入る」:バイト数です。日本語やBase64化したJSONはすぐに上限に達します。
  • 「大きいCookieは切り詰めて保存される」:切り詰めではなく、Cookie全体が無視されます。
  • 「暗号化すればCookieにデータを持たせてよい」:暗号化・署名でサイズは増えます。Cookieには識別子だけを入れ、データ本体はサーバー側セッションに置くのが基本です。

Cookieの属性(Secure・HttpOnly・SameSite・有効期間など)は、「CookieのSecure属性」、「CookieのHttpOnly属性」、「CookieのSameSite属性」、「Cookieの有効期間が過度に長くない」の各項目で確認します。このページは名前と値の大きさだけを扱います。

Cookie名・値のサイズ上限の診断基準(セキュリティAIチェッカー)

取得対象

  1. トップページ(リダイレクトを最大4回追跡した最終URL)の応答。
  2. トップページのHTMLから抽出した同一オリジンのページを、ログイン系パスを優先して最大4ページGETした応答(合計最大5ページ)。各ページのリダイレクトは最大3回、応答本文は最大500,000バイト、タイムアウトは7秒です。
  3. 各応答の Set-Cookie を1件ずつ取得します。

リダイレクト途中の応答のSet-Cookie、ログイン後のCookie、JavaScriptで設定されるCookieは対象外です。

計算方法

各 Set-Cookie 値について次のように計算します。

  1. 最初の ; より前を「名前=値」部分として取り出す。
  2. 最初の = で名前と値に分け、それぞれの前後の空白を除く。= が無い場合は名前を空、全体を値とする。
  3. 名前と値のバイト数(サーバーが送信したオクテット数)を合計する。非ASCII文字は、UTF-8で送信されていれば1文字3バイトなど実際の送信バイト数で数える。

判定条件

判定条件得点への影響
対象外(na)巡回したどの応答でもCookieが発行されていない採点から除外
○ 問題なし(pass)観測したすべてのCookieで名前+値が4096バイト以下重み2×1.00
× 要改善(fail)名前+値が4096バイトを超えるCookieが1件以上ある重み2×0
  • 4096バイトを超えるCookieはブラウザに保存されず、機能不全が確定的であるため「要確認」ではなく「要改善」とします。
  • 根拠欄には「超過件数/観測件数」を表示します。
  • 重大度はmedium、重みは2です。

自治体サイトでの判定例

状況判定
CMSが静的ページを配信しCookieを発行しない対象外
アクセス解析やロードバランサーの振り分け用Cookie(数十バイト)のみ○ 問題なし
電子申請・施設予約システムが、入力途中のフォーム内容をBase64化したJSONとしてCookieに保存し、5,000バイトを超えている× 要改善
同意管理ツールが同意内容を詳細なJSONでCookieに入れ、名前+値がちょうど4096バイト○ 問題なし(上限ちょうどは許容範囲)

電子申請の例では、ブラウザはこのCookieを保存しないため、入力内容が失われます。同意管理ツールの例は合格ですが、余裕がないため縮小が望まれます。

判定の限界

観測できるのは公開ページで発行されるCookieだけです。ログイン後に大きくなるCookie(権限情報を詰めたJWTなど)は観測できないため、手動確認を推奨します。また、Cookieの総数や Cookie リクエストヘッダー全体の大きさは本項目では評価しません。

Cookieがサイズ上限を超えるとどんなリスクがあるか

  • 認証・セッションの不具合:セッション情報を詰め込んだCookieが上限を超えると、ログインしても直後に未ログイン扱いになります。利用者の再試行が増え、窓口への問い合わせにつながります。
  • CSRF対策の無効化・誤動作:Double Submit Cookie方式などでCookieにトークンを置く場合、Cookieが保存されないと正規の送信まで拒否されるか、実装によっては検証が省略される不具合を招きます。
  • サービス停止(自己DoS):大きなCookieが複数蓄積すると、リクエストヘッダーがサーバーの上限を超え、400/431エラーでサイト全体が表示できなくなります。Cookieを削除しない限り復旧しないため、利用者側では原因が分かりません。
  • 情報の過剰保存:大きなCookieは、本来サーバー側に置くべき個人情報や業務データをクライアントに保存している兆候です。端末の共有や盗難で情報が露出する可能性が高まります。

Cookieのサイズ超過そのものを直接の原因とする、公表された大規模なセキュリティ事故は確認できていません。本項目は主に、可用性と設計上の問題を早期に検出するためのものです。

Cookieを4096バイト以下にする対策(PHP・Next.js・Apache・nginx・IIS)

基本方針

  1. Cookieにはランダムなセッション識別子だけを入れ、データはサーバー側(セッションストア、DB、Redis等)に保存する。
  2. どうしてもクライアントに状態を持たせる場合は、項目を絞り、署名付きの短い表現にする。
  3. 同じ目的のCookieを複数作らないよう、名前とPathを整理する。
  4. 不要になったCookieは Max-Age=0 で削除する。

PHP(サーバー側セッションへ移行)

<?php
// NG: フォーム内容をCookieへ保存
// setcookie('form', base64_encode(json_encode($_POST)));

// OK: セッションIDのみCookie、データはサーバー側
session_set_cookie_params([
  'path' => '/', 'secure' => true, 'httponly' => true, 'samesite' => 'Lax',
]);
session_start();
$_SESSION['form_draft'] = $sanitizedInput;

Next.js(Route Handler)

import { NextResponse } from "next/server";

export async function POST(req: Request) {
  const draft = await req.json();
  const id = crypto.randomUUID();
  await saveDraft(id, draft);        // サーバー側ストアへ保存
  const res = NextResponse.json({ ok: true });
  res.cookies.set({ name: "__Host-draft", value: id, path: "/",
    secure: true, httpOnly: true, sameSite: "lax" });
  return res;
}

Apache / nginx(ヘッダー上限の確認)

Cookieの縮小が根本対策ですが、障害時の切り分けとしてサーバー側上限も確認します。

# Apache: 既定は8190バイト。むやみに引き上げない
LimitRequestFieldSize 8190
# nginx: 既定は 4 8k
large_client_header_buffers 4 8k;

上限を大きくするとメモリ消費やDoS耐性に影響するため、引き上げは一時的な回避に限ります。

IIS

IISでは HTTP.sys の MaxFieldLength・MaxRequestBytes レジストリ値がヘッダー上限です。設定変更はOS全体に影響するため、Cookie縮小を優先します。

Cookieのサイズの確認方法

# Set-Cookieごとに「名前+値」のバイト数を表示
curl -sI https://www.city.example.lg.jp/ \
  | grep -i '^set-cookie:' \
  | sed -E 's/^[Ss]et-[Cc]ookie: *//; s/;.*$//' \
  | while IFS= read -r pair; do
      n=$(printf '%s' "$pair" | tr -d '\r' | sed 's/=//' | wc -c)
      echo "$n bytes : ${pair%%=*}"
    done

ブラウザの開発者ツール(Application → Cookies)の「Size」列でも確認できます。ただし数え方(文字数かバイト数か)はツールにより異なる場合があるため、判定は上記のバイト数計算で行います。修正後はセキュリティAIチェッカーで再診断し、根拠欄の超過件数が0になったことを確認します。

サイトを壊さないための注意点(ガードレール)

  • Cookieの構造を変えるときは、旧形式のCookieを読み取る処理を一定期間残し、利用者がログアウトさせられないようにします。
  • Cookieを削除する際は、発行時と同じ Path・Domain を指定しないと削除されません。
  • JWTをCookieに入れる場合、権限やプロフィールを詰め込むとすぐに数KBに達します。クレームは最小限にし、詳細はサーバーで引きます。

よくある質問(FAQ)

Cookie1つあたりの最大サイズは何バイトですか?

名前と値の長さの合計で4096バイト(オクテット)です。draft-ietf-httpbis-rfc6265bisとOWASP ASVS 5.0.0 V3.3.5がこの上限を定めています。属性はこの合計に含まれず、各属性値は別に1024オクテットまでと制限されます。

4096文字まで入れられるということですか?

いいえ、文字数ではなくバイト数です。UTF-8で日本語を直接入れると1文字が3バイトになり、Base64化したJSONもすぐに上限に達します。

上限を超えたCookieは切り詰めて保存されますか?

切り詰めではなく、Cookie全体が無視されます。エラー表示もないため、ログイン状態が保持されない、同意バナーが何度も出るといった不具合の原因が分かりにくくなります。

4096バイトちょうどのCookieは問題ありませんか?

上限ちょうどは許容範囲で、セキュリティAIチェッカーでも「○ 問題なし」です。ただし余裕がないため、項目を減らすなど縮小が望まれます。

Cookieが原因で「400 Bad Request」や「431」エラーになるのはなぜですか?

Cookieが多数あると、ブラウザが送るCookieヘッダー全体がサーバーのヘッダー上限(Apacheは既定8190バイト、nginxは既定8KBなど)を超えるためです。個々のCookieが4096バイト以下でも起こります。この合計の大きさは本項目では評価しません。

暗号化すればCookieにデータを保存してもよいですか?

暗号化や署名をするとサイズはむしろ増えます。Cookieにはランダムな識別子だけを入れ、データ本体はサーバー側のセッションやDBに保存するのが基本です。

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

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

参考資料