メインコンテンツへスキップ
ブログ一覧に戻る
Web制作・運用

SameSite=LaxはCSRF対策になるのか|仕様の草案が「減速帯」と書いている理由

2026年10月7日
12分で読めます
SameSite=LaxはCSRF対策になるのか|仕様の草案が「減速帯」と書いている理由

この記事の結論

SameSite属性を設定すればCSRF対策は完了なのか判断したい方へ。Cookie仕様の草案はLax強制を多層防御の一枚と位置づけ、回避手段を2つ挙げたうえで、CSRFはセッション管理側でより完全に緩和できると別節を指しています。原文の記述と、設計書・報告書を受け取る側が踏む確認手順を整理します。

SameSite=LaxはCSRF対策になるのか

設計書やセキュリティ報告書に「Cookieに SameSite=Lax を設定済み。CSRF対策は完了」という一行が入っていることがあります。受け取る側としては、この一行をどう扱えばよいのかが判断しにくいところです。

CSRF(クロスサイトリクエストフォージェリ/利用者が意図しない操作を、別サイトから利用者のログイン状態を使って実行させる攻撃)は、Cookieが勝手に送られることで成立します。SameSite属性はCookieが送られる範囲を狭めます。したがって対策になる——この推論は筋が通っているように見えます。

最初は、これで足りると考えていました。送られる範囲を狭めれば攻撃は成立しない、という理解です。しかし仕様の草案そのものを読むと、書いてある内容が違いました。草案は、Lax強制がCSRFという攻撃カテゴリ一般に対する堅牢な防御を提供しないと明記し、その回避手段まで自分で挙げています。

本記事が立てる仮説はこれです——SameSite属性は「CSRFを防ぐ機能」ではなく「Cookieが送られる範囲を狭める機能」であり、両者を同じものとして扱うと、対策が1枚しかない設計を「完了」と呼んでしまうのではないか。

この仮説が当たっているなら、起きる失敗は具体的です。SameSiteを設定し、CSRF対策の項目にチェックを入れ、トークンの実装を見送る。後から「属性を1つ設定しただけで、代わりに外した対策は何だったのか」を説明できない——判断の記録が残らないまま、層が1枚減った状態が引き継がれます。

本記事は、設計書・報告書の記述をどう読むかに特化します。CSRFトークンの具体的な実装方法や推奨アルゴリズム、個別ブラウザの実装状況は扱いません。認証の全体像はモダンなWeb認証で扱っています。

30秒で要点

  • Cookie仕様の草案(draft-ietf-httpbis-rfc6265bis-22、2026年9月30日時点でRFC化されていない)は、Lax強制がPOSTのようなunsafeなメソッドに依存するCSRF攻撃に対しては妥当な多層防御を提供するが、CSRFという攻撃カテゴリ一般に対する堅牢な防御は提供しないと書いている
  • 草案は回避手段を2つ自分で挙げており、一方を「攻撃への道における減速帯(speedbump)にすぎない」と表現している
  • 草案は、開発者はCSRFをセッション管理の仕組みによってより完全に緩和できるとして、別の節を指している
  • 「SameSite属性を書かなかったCookie」と「SameSite=Lax と明示したCookie」は、同じ扱いになるとは限らない
  • したがって判断軸は「SameSiteは外さない。ただし他の対策の代わりにもしない」になる

なぜ「SameSiteを設定すればCSRF対策は完了」と読めてしまうのか

この誤読は、知識不足から生まれるというより、2つの構造から生まれます。

第一に、属性の設定は完了を宣言しやすい作業だという事情があります。SameSite=Lax と書いたかどうかは、コードを見れば一目で分かります。一方、CSRF対策が十分かどうかは、どの経路でどの操作が実行されうるかを辿らないと分かりません。チェックリストの上では、前者は「済」と書けて後者は書けません。済と書ける項目は、書けない項目を代表してしまうことがあります。

第二に、対策の名前と機能の名前が近いという事情があります。CSRFは「クロスサイト」の攻撃であり、SameSiteは「同一サイト」を扱う属性です。語が対応しているため、片方がもう片方を打ち消すように読めます。しかし属性が決めているのはCookieの送信範囲であって、要求の正当性ではありません。

この構造を踏まえずに設計を進めると、層が減ったことに誰も気づきません。属性が設定されている以上、レビューでも指摘されにくくなります。

仕様の草案は Lax を「多層防御」と位置づけ、回避手段まで挙げている

ここで参照するのは、Cookieの仕様を更新するIETFの草案 draft-ietf-httpbis-rfc6265bis-22 です[^1]。2026年9月30日の確認時点でRFCとして発行されておらず、Internet-Draftの段階にあります。文書日付は2025年12月、著者欄は Bingler, et al. です。RFC 6265(2011年に発行済みの文書)とは別物なので、引用するときは版数と確認日を添える必要があります。

草案の該当節(5.6.7.1)は、Lax強制について次のように書いています——Lax強制はPOSTのようなunsafeなHTTPメソッドに依存するCSRF攻撃に対しては妥当な多層防御(defense in depth)を提供するが、CSRFという攻撃カテゴリ一般に対する堅牢な防御は提供しない。

注目すべきは、この文がコロンで終わり、直後に理由が2点列挙されていることです。つまり草案は、「防げない」と述べるだけでなく、どう回避されうるかを自分で示しています。

  1. 攻撃者は新しいウィンドウを開いたり、トップレベルナビゲーションを起こすことで「同一サイト(same-site)」扱いの要求を作れる。これは攻撃への道における減速帯(speedbump)にすぎない
  2. <link rel='prerender'> のような機能は、ユーザーに検知されるリスクなく「同一サイト」扱いの要求を作るために悪用されうる

1点目は、Laxが許している範囲そのものを使う回避です。LaxはクロスサイトのトップレベルナビゲーションではCookieを送ります。そこを通せば、要求は同一サイト扱いになります。

そして草案は結論として、開発者はCSRFをセッション管理の仕組みによってより完全に緩和できると述べ、別の節(8.8.2)を指しています。本記事の確認では、その節の本文は読んでいません。したがって「草案が別節を参照している」ことまでが、ここで書ける範囲です。どの手法を推奨しているかは、原文を自分で開いて確認する必要があります。

もう1つ、同じ節の直前に置かれた注記も実務上効いてきます。リダイレクトの途中でメソッドがPOSTからGETに変わることがあり、その場合、要求が "safe" かどうかは現在のリダイレクトホップのメソッドで判定されます。「このエンドポイントはPOSTだから守られている」という前提は、リダイレクトを挟むと崩れうるということです。

「属性を書かなかったCookie」と「Laxと書いたCookie」は同じではない

もう1つ、設計レビューで見落とされやすい区別があります。

草案の 5.6.7.2 は、"Lax-allowing-unsafe" について、これはSameSite属性の値ではなく強制モードであると述べています。そしてユーザーエージェント(ブラウザ等)は、これを「SameSite属性を明示的に指定しなかったCookieにだけ」適用してよい(MAY)とされています。

つまり、属性を書かなかったCookieと SameSite=Lax と明示したCookieは、同じ扱いになるとは限りません。「既定でLaxになるのだから書かなくても同じ」という前提は、草案の記述とは一致しません。

同じ節は、この互換モードを適用するユーザーエージェントについて、対象を「最近作られたCookie」に限定すべき(SHOULD)としており、"Deployment experience has shown a cookie age of 2 minutes or less to be a reasonable limit." と続けています。2分という数値はここで一度だけ出てきますが、これは運用経験に基づく妥当な上限の目安として SHOULD で書かれた値であり、仕様が全ブラウザに義務づけた閾値ではありません。数値を引くときは、この文脈ごと引く必要があります。

値の意味そのものも、草案の 4.1.2.7 に整理されています。

値Cookieが送られる範囲
Strict同一サイト要求のみ
Lax同一サイト要求と、クロスサイトのトップレベルナビゲーション
None同一サイト要求とクロスサイト要求の両方

この3つ以外の値を書いた場合、その値はLax相当の既定強制モードの対象になります。そしてユーザーエージェントが "Lax-allowing-unsafe" 強制を使う場合、その既定は "Lax-allowing-unsafe" 相当になります。綴りを間違えた値が「設定されていない」ではなく「別のモード」として扱われるという点は、設定の検証時に押さえておく価値があります。

確かなことと、まだ確かめきれていないこと

確かなこと: 上記の引用は、Internet-Draft の原文テキスト(draft-ietf-httpbis-rfc6265bis-22)を取得して該当節を行単位で確認したものです。Lax強制の位置づけ、回避手段の2点、別節への参照、Lax-allowing-unsafe の扱い、3つの値の意味は、いずれも草案本文に書かれています。

まだ確かめきれていないこと: この文書は草案であり、RFCとして発行されていません(2026年9月30日確認)。内容は今後変わりえます。また本記事が原文を確認したのは 5.6.7.1 / 5.6.7.2 / 4.1.2.7 の各節と、5.6.7.1 直前の注記のみです。参照先として挙がっている 8.8.2 およびセキュリティ考慮事項の各節は読んでいません。

個別ブラウザが既定値をいつどう変えたか、現在の実装がどうなっているかも、本記事の確認範囲外です。草案はこれらをユーザーエージェントの任意(MAY)として書いており、実装の実態は仕様書からは分かりません。「主要ブラウザは既定でLaxだから大丈夫」という判断は、本記事の情報源では裏付けられません。

判断軸:SameSiteは外さない。ただし代わりにもしない

ここまでの整理から導かれる判断軸は1行です——SameSite属性は多層防御の一枚として重ね、外さない。ただし他の対策の代わりにはしない。

この軸は、2つの極を同時に退けます。

  • 「SameSiteがあるからトークンは不要」——草案自身が堅牢な防御を提供しないと書き、回避手段を2つ挙げている。この読み方は草案と矛盾します
  • 「SameSiteは防げないから意味がない」——草案は妥当な多層防御(defense in depth)と位置づけています。一枚の層としての価値は認められています

同じ構造は、他の「設定すれば済むように見える機能」にも現れます。CORSは共有を許す仕組みであって遮断する仕組みではないで扱っている論点と、本記事は対になります。どちらも、機能が実際に決めている範囲と、対策として期待される範囲がずれているという同じ形をしています。

設計書・報告書を受け取ったときの確認手順

判断軸を試すのに、コードを読む必要はありません。手元の設計書1つで足ります。

  1. 「SameSite」という語が出てくる箇所を探す
  2. その記述がどの項目の下に書かれているかを見る。「Cookie設定」の下にあるなら整合します。「CSRF対策」の下にあり、それが唯一の記述なら、2へ進む前に止まります
  3. 状態を変える操作(登録・変更・削除・送金・設定変更)を列挙する。これが分母です
  4. そのうち、SameSite属性以外の対策が書かれていないものを数える。これが分子です
  5. 分子が0でないなら、その件数と対象エンドポイントを質問として返す

4で数えるのは「対策が無い」ではなく「設計書に書かれていない」です。実装されていても文書に無ければ、引き継いだ人には存在しません。この区別をつけたまま質問を返すと、相手も答えやすくなります。

リダイレクトを挟む経路がある場合は、3の列挙にリダイレクト後のメソッドも書き添えます。草案の注記のとおり、safe かどうかは現在のホップのメソッドで判定されるためです。

外部から読み込んでいるスクリプトの棚卸しについてはthird-party スクリプトの棚卸しで扱っています。Cookieが送られる範囲を考えるとき、そこに何が載っているかは別途数える必要があります。

判断に迷ったときに立ち返る問い

設定項目を前にしたときに立ち返りたいのは、「この機能が実際に決めているのは何か」という問いです。SameSiteが決めているのはCookieの送信範囲です。要求が正当かどうかは決めていません。範囲を狭めることと正当性を確かめることは、別の仕事です。

もう1つは、「仕様書は自分でこの機能の限界を書いていないか」という問いです。この例では、書いてありました。回避手段まで列挙されていました。実装者向けの文書が自分で限界を書いているとき、その記述は読み手が持ち出せるもっとも強い根拠になります。

自社の設計レビューでこの種の確認を仕組みに落としたい場合は、無料診断ツールで状況を言語化するところから始めることができます。

状況を整理する(15分)

[^1]: draft-ietf-httpbis-rfc6265bis(版数 -22、著者欄 Bingler, et al.、Internet-Draft、文書日付2025年12月、2026年9月30日確認)。原文テキストはdraft-ietf-httpbis-rfc6265bis-22.txtを取得し、5.6.7.1 / 5.6.7.2 / 4.1.2.7 を確認した。RFCとして発行された文書ではない。

よくある質問(FAQ)