結論(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名・値のサイズ上限 |
|---|---|
| 項目ID | cookie.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) |
|---|---|---|
abc123 | 6 | 6 |
申請中(日本語を直接) | 3 | 9 |
| 1,400文字の日本語 | 1,400 | 4,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チェッカー)
取得対象
- トップページ(リダイレクトを最大4回追跡した最終URL)の応答。
- トップページのHTMLから抽出した同一オリジンのページを、ログイン系パスを優先して最大4ページGETした応答(合計最大5ページ)。各ページのリダイレクトは最大3回、応答本文は最大500,000バイト、タイムアウトは7秒です。
- 各応答の
Set-Cookieを1件ずつ取得します。
リダイレクト途中の応答のSet-Cookie、ログイン後のCookie、JavaScriptで設定されるCookieは対象外です。
計算方法
各 Set-Cookie 値について次のように計算します。
- 最初の
;より前を「名前=値」部分として取り出す。 - 最初の
=で名前と値に分け、それぞれの前後の空白を除く。=が無い場合は名前を空、全体を値とする。 - 名前と値のバイト数(サーバーが送信したオクテット数)を合計する。非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)
基本方針
- Cookieにはランダムなセッション識別子だけを入れ、データはサーバー側(セッションストア、DB、Redis等)に保存する。
- どうしてもクライアントに状態を持たせる場合は、項目を絞り、署名付きの短い表現にする。
- 同じ目的のCookieを複数作らないよう、名前とPathを整理する。
- 不要になった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に保存するのが基本です。
この項目を含む127項目を、URLを入れるだけで無料診断します。