Cookie 属性ガイド:SameSite・Partitioned・HttpOnly・Secure・Domain・Path・Priority の使い分け

約11分

Set-Cookie ヘッダの属性は 7 種類以上あり、認証・CSRF 対策・トラッキング規制対応にすべてが絡みます。「SameSite=Lax でいい」「HttpOnly を付けておけば安全」と単発で覚えがちですが、現代では Partitioned の登場や 3rd-party Cookie 廃止トレンド で組合せ判断が増えています。本記事では各属性の役割と、典型的な用途別の推奨組合せを整理します。

属性一覧

Set-Cookie: sessionId=abc123; Domain=example.com; Path=/; Max-Age=3600;
            Secure; HttpOnly; SameSite=Lax; Priority=High; Partitioned
属性役割デフォルト
Domain送信先ドメイン範囲リクエストのオリジン
Path送信先パス範囲リクエストのパス
Expires / Max-Age有効期限セッション(タブ閉じで消える)
SecureHTTPS のみ送信なし(HTTP でも送る)
HttpOnlyJS から読めないなし(document.cookie で読める)
SameSiteクロスサイト送信を制御Lax(モダンブラウザ)
Partitionedパーティション分離(CHIPS)なし
Priorityエビクション優先度Medium

SameSite:CSRF と トラッキングの境界

最も重要な属性。クロスサイトリクエストでの送信挙動を制御。

クロスサイト GET(リンク)クロスサイト POST(フォーム)iframe 内
Strict
Lax
None✓(要 Secure

SameSite=Lax(現代のデフォルト)

Chrome 80(2020)以降、SameSite を指定しないと暗黙で Lax 扱いになります。

  • 同一サイト:常に送信
  • クロスサイトのトップレベル GET(<a href> クリックで遷移など):送信する
  • クロスサイトの POST、iframe 読込、画像読込:送信しない

CSRF 対策の主要ライン。「フォーム POST が他サイトから来る」攻撃を防ぐ。

SameSite=Strict

クロスサイトでは一切送信しない。トップレベル遷移であっても他サイトから来たら送らない。

「外部サイトのリンクをクリックしてアクセスしたユーザーは、ログイン状態が一旦切れる」という挙動になります。これを避けるにはログインクッキーを 2 つ持つ設計(短期 Strict + 長期 Lax)が定番。

SameSite=None(要 Secure

すべてのクロスサイトコンテキストで送信。従来の 3rd-party Cookie 挙動

ブラウザは SameSite=None だが Secure がない Cookie を拒否Chrome 80+)。HTTPS が前提。

Partitioned(CHIPS):3rd-party Cookie の置き換え

Set-Cookie: id=abc; Secure; SameSite=None; Partitioned

CHIPS(Cookies Having Independent Partitioned State) は、埋め込み元サイトごとに別パーティションでクッキーを持たせる機能。

動機

3rd-party Cookie の用途のうち、正当なもの(埋め込み iframe チャットの状態保持、CMS の埋め込みプレビュー認証など)は残したい。一方、クロスサイトトラッキング(同じ Cookie 値で複数サイトのユーザー追跡)は防ぎたい。

Partitioned は「クッキーを使えるが、埋め込み元サイトごとに別ストア」という解:

  • chat.example.com の iframe を siteA.com に埋め込む → siteA.com 用パーティションにクッキー保存
  • 同じ iframe を siteB.com に埋め込む → siteB.com 用のパーティション
  • 結果、chat.example.com 側からは「siteA に来たユーザー」と「siteB に来たユーザー」を同一視できない

使い時

  • 自社の embeddable widget(チャット、コメント、決済 iframe)
  • 3rd-party Cookie の代替が要るが、サイト横断トラッキングは目的でないケース

逆にトラッキングが目的の Cookie は、Partitioned ではユースケースが成立せず、別の仕組み(First-Party Set, Privacy Sandbox API)に移行する必要があります。

HttpOnly と Secure

HttpOnly

JavaScript からアクセスできないクッキー:

Set-Cookie: sessionId=abc; HttpOnly
  • document.cookie で取得・設定できない
  • HTTP リクエストには通常通り送信される
  • XSS でクッキーを盗まれるのを防ぐ最大の防衛線

セッション ID・認証トークンには必ず HttpOnly を付ける。

Secure

HTTPS でのみ送信:

Set-Cookie: sessionId=abc; Secure
  • HTTP リクエストには送らない
  • 中間者がクッキーを抜き取るのを防ぐ
  • SameSite=None 使用時は必須

開発環境(HTTP の localhost)と本番(HTTPS)で挙動を変えたい場合:

const secure = process.env.NODE_ENV === 'production';
res.cookie('sessionId', value, { secure, httpOnly: true });

Domain と Path

Domain

Set-Cookie: id=abc; Domain=example.com

このクッキーは example.com および すべてのサブドメインapi.example.comwww.example.com など)に送信される。

省略すると、Set-Cookie を返したサーバ自身のホストにのみ送信(サブドメインを含まない)。サブドメイン間で共有したいときは明示的に親ドメインを指定。

Path

Set-Cookie: id=abc; Path=/admin

/admin 以下のパスでだけ送信。/admin/users には送信、/dashboard には送信しない。

実用上は Path=/ が多い。Path で絞ることでクッキーが多くなるサイトのヘッダサイズ削減に使う場合がある。

Expires と Max-Age

Set-Cookie: id=abc; Max-Age=3600
Set-Cookie: id=abc; Expires=Thu, 01 Dec 2026 16:00:00 GMT
属性単位解釈基準
Max-Age受信時刻からの相対
ExpiresUTC 日時クライアントの時計

両方ある場合は Max-Age が優先。クライアント時計のずれを避けたいので Max-Age 推奨。

Max-Age=0 または過去の Expiresクッキー削除の指示。同じ name / Domain / Path で送信し直す必要があります。

Priority(Chrome 拡張)

Set-Cookie: id=abc; Priority=High

ブラウザがクッキー数の上限に達したとき、どれから消すかを制御。Low / Medium(既定) / High。Chrome 系のみで実装、Firefox / Safari は無視。

通常は気にしなくてよく、認証用クッキーが頻繁に揮発する場合の応急対応に使う程度。

認証クッキーの推奨組合せ

Set-Cookie: sessionId=abc;
            Path=/;
            Max-Age=3600;
            Secure;
            HttpOnly;
            SameSite=Lax
  • Path=/:サイト全体で利用
  • Max-Age=3600:1 時間(必要に応じてリフレッシュ)
  • Secure:HTTPS のみ
  • HttpOnly:XSS 耐性
  • SameSite=Lax:CSRF 耐性

Domain は明示しない:サブドメイン共有が必要なときだけ追加(共有しない方が攻撃面が小さい)。

CSRF 対策の現代的アプローチ

SameSite=Lax だけでは完全な CSRF 対策にならないケースがあります:

  • POST 以外の変更系メソッド(PUT / DELETE):Lax でもクロスサイトでは送られないので OK
  • GET で副作用がある古い APILax で送られてしまう(GET をクロスサイトで投げれば認証が通る)
  • iframe 内アプリケーション:Lax では送られないので問題ない

加えて、Double Submit Cookie パターン(クッキーの値と同じ値を別ヘッダ・別フォーム値で送らせて検証)を組み合わせると、Cookie が漏れない限り CSRF を防げます:

// Cookie に CSRF token をセット
Set-Cookie: csrfToken=xyz; Secure; SameSite=Lax

// クライアントは Cookie を読んで(HttpOnly でない CSRF 用 Cookie は別物)
// 同じ値を X-CSRF-Token ヘッダに付けて送信
fetch('/api/transfer', {
	headers: { 'X-CSRF-Token': getCsrfToken() }
});

ブラウザ間の差

機能ChromeFirefoxSafari
SameSite=Lax デフォルト
Partitioned (CHIPS)✓ (118+)✓ (131+)
Priority
3rd-party Cookie 廃止計画変更(保留)デフォルト無効デフォルト無効(ITP)

Safari の ITP(Intelligent Tracking Prevention)は最も厳しく、Partitioned も未対応。Safari でユーザーが失われる前提で、3rd-party Cookie に依存する設計を避けるのが現代的。

まとめ

Cookie 属性は 「誰に送るか(Domain / Path / SameSite)」「どう守るか(Secure / HttpOnly)」「いつ消すか(Max-Age / Expires)」「分離するか(Partitioned)」 の 4 軸で整理できます。認証用クッキーは Secure + HttpOnly + SameSite=Lax を最小ラインに、3rd-party 用途では SameSite=None + Secure + Partitioned を組み合わせるのが 2026 年の標準形です。Safari 等で Partitioned 未対応の場合は機能が縮退する前提を持つこと。