- ブラウザURL入力今ここ
- DNS名前→IP
- ルータ経路選択
- ロードバランサ振り分け
- Nginx受け口
- アプリ処理
- DB保存
前回は、フォームが送れた範囲の要求は確かめずに送られることを見ました。今回は、そうした要求に Cookie を付けるかどうかの判定単位を見ます。
まず結論
SameSite が比べるのは origin ではなく site(scheme + registrable domain)です。`https://a.example.test` と `https://b.example.test` は origin が違っても同じ site なので、手元の実測では3エンジンとも、兄弟から来た POST に `SameSite=Strict` の Cookie が付きました。
このコースの芯は「ブラウザが確かめられるのは『どこから来たか』まで、『本人が望んだか』はサーバが自分で確かめるしかない」でした。SameSite はその『どこから』を site の粒さで見る仕組みで、属性を書かなかった Cookie の扱いはエンジンごとに違います。
b.example.test が SameSite=None / Lax / Strict / 属性なし の4つの Cookie を発行しました。そのあと a.example.test のページのフォームから b.example.test へ POST すると(どちらも https・同じポート)、headless Chromium ではどの Cookie が付くでしょうか。
当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。
SameSite の Same は、origin ではなく site
SameSite は名前のとおり「同じ site か」を見ます。6265bis は同じ site かどうかを自分では定義せず、HTML Standard に任せています。
Two origins are same-site if they satisfy the "same site" criteria defined in [SAMESITE].
参照先の HTML では、site は origin から (origin's scheme, origin's host's registrable domain) を取り出したものです。比べるのは scheme と registrable domain だけで、ポートとサブドメインは比較に入りません。ブラウザの仕組み『分離の単位は origin ではなく site』で見た scheme + eTLD+1 と同じものです。
registrable domain は public suffix に左のラベルを1つ足したもので、どこまでが public suffix かは Public Suffix List(PSL)が決めます。どの規則にも当たらないときは既定規則 * により最右のラベルが public suffix になります。
今回の実験で使った .test は PSL に載っていません。したがって a.example.test と b.example.test の registrable domain はどちらも example.test で、同じ site です。一方 a.test と b.example.test は別の site です。
- ・origin は別でも site は同じ。SameSite の線は site の境目にしか引かれない
- ・`.test` は PSL に無いので、既定規則 `*` で `test` が public suffix になる
兄弟サブドメインから来た POST に、Strict が付く
自前サーバ(自己署名証明書、全ホスト名を 127.0.0.1 へ流す)で、b.example.test が次の4つを発行します。
c_none=exp4; SameSite=None; Secure; Path=/c_lax=exp4; SameSite=Lax; Secure; Path=/c_strict=exp4; SameSite=Strict; Secure; Path=/c_unspec=exp4; Secure; Path=/
続いて a.example.test のページのフォームから b.example.test へ POST し、対照として a.test からも同じ宛先へ POST しました。同じことを example.com 系の名前でも行っています(外部には接続していません)。
b.example.test origin=https://a.example.test:8443 sec-fetch-site=same-sitecookie: c_none=exp4; c_lax=exp4; c_strict=exp4; c_unspec=exp4b.example.com origin=https://a.example.com:8443 sec-fetch-site=same-sitecookie: c_none=exp4com; c_lax=exp4com; c_strict=exp4com; c_unspec=exp4comb.example.test origin=https://a.test:8443 sec-fetch-site=cross-sitecookie: c_none=exp4; c_unspec=exp4
origin が別なのに c_strict が付いています。 ブラウザ自身も sec-fetch-site で same-site と申告しています。別の site である a.test から来た要求では、Lax と Strict が外れました。属性なしの c_unspec が残っている理由は、後で見ます。Firefox 155・WebKit 26.6(どちらも Playwright 同梱版)でも各2回、Cookie の並び順を除いて同じ結果です。
Cookie は Domain 属性なしなので、送り先は b.example.test に限られます。「どのホストへ送るか」と「どこから来た要求か」は別の判定で、SameSite が見ているのは後者です。
`https://b.example.test` の Cookie に `SameSite=Strict` を付けました(Domain 属性なし)。`https://a.example.test` のページから b.example.test へ要求が出たとき、この Cookie はどうなりますか。
境界の位置も、既定値も、ブラウザ側の知識で決まる
SameSite の判定には、ブラウザが持っている知識が2つ入り込みます。
1つ目は PSL です。URL Standard は、registrable domain について次のように注意しています。
The notion of "public suffix" and "registrable domain" cannot be relied-upon to provide a hard security boundary, as the public suffix list will diverge from client to client.
site の境目は、ブラウザが持つ一覧の版で動きえます。
2つ目は、属性を書かなかった Cookie の扱いです。6265bis は属性なしの Cookie の same-site-flag を Default とし、取り出しの手順で Lax と同じ扱いにします。そのうえで、互換のための緩いモードを認めています。
user agents MAY apply "Lax-allowing-unsafe" enforcement only to cookies that did not explicitly specify a SameSite attribute
適用するなら最近作られた Cookie に限るべき(SHOULD)とし、2 minutes or less を運用経験上の目安として挙げます。2分は MAY のモードの中の SHOULD の目安で、上限の規定ではありません。
仕様は Lax 自体の効き目にも限定を付けています。does not offer a robust defense against CSRF as a general category of attack(§5.6.7.1)。Strict についても、それだけを CSRF 対策の全部にしないよう求めています(§8.8.1)。
属性を書かなかった Cookie は、エンジンで分かれる
b.test が発行した直後に a.test から POST し、125秒待ってもう一度 POST しました(Playwright 同梱版の headless。市販のブラウザそのものではありません)。
chromium 153.0.8010.12 t+0s c_none=wchromium1; c_unspec=wchromium1t+125s c_none=wchromium1firefox 155.0 t+0s c_none=wfirefox1; c_unspec=wfirefox1t+125s c_none=wfirefox1; c_unspec=wfirefox1webkit 26.6 t+0s c_none=wwebkit1; c_unspec=wwebkit1t+125s c_none=wwebkit1; c_unspec=wwebkit1
一次ソースと突き合わせると、次のようになります。
エンジン 一次ソース 実測(125秒後)Chromium 既定は Lax。作成2分以内は Lax-allowing-unsafe 付かないFirefox network.cookie.sameSite.laxByDefault の既定は false 付くWebKit lax-by-default に当たる設定が見当たらない 付く
Chromium は kLaxAllowUnsafeMaxAge = base::Minutes(2) で、仕様の目安と一致します。ただし LEGACY のアクセス方式では None 扱いに戻る分岐がソースにあります。chromestatus では M85 で既定有効、2020年7月14日から段階的に展開とされています。
WebKit は、Apple 版の Cookie 処理が非公開の CFNetwork 側にあるため、オープンソースだけでは製品版 Safari の挙動を確定できません。Edge も確かめていません。
「今のブラウザは属性なしの Cookie を Lax として扱うので、SameSite を書かなくてよい」という主張の扱いとして適切なのはどれですか。
SameSite の Cookie
a.example.test から来た POST に、b.example.test の Strict の Cookie が付きました。兄弟から来た要求は、Cookie の持ち主と同じ側として扱われます。
比べる単位 site(scheme + registrable domain)a.example.test → b same-site(Strict も付く)a.test → b cross-site(Lax・Strict は外れる)
Site Isolation のプロセス分離
ブラウザの仕組み『分離の単位は origin ではなく site』で見たとおり、Chromium の分離も site 単位でした。a.example.com と b.example.com は同じ site なので、同じプロセスを共有しえます。
比べる単位 site(scheme + eTLD+1)a.example.com と b 同じプロセスを共有しうる
Cookie の送信判定とプロセス分離。仕組みは違いますが、兄弟サブドメインの扱いに共通するのは何でしょうか。
「サブドメインを分けた」ことで、それぞれの仕組みの線の外に出られるかを考えてください。
この章のまとめ
- SameSite が比べるのは site = (scheme, registrable domain)。ポートとサブドメインは入らない。
a.example.testから来た POST にb.example.testの Strict の Cookie が付いた(3エンジン×2回)。別の site の a.test からでは Lax と Strict が外れた。.testは PSL に無く、既定規則*でtestが public suffix になる。site の境目は PSL の版で動きうる。- 属性なしの扱いはエンジンで違う。Chromium は Lax(作成2分以内は Lax-allowing-unsafe)、Firefox の既定値は false、Playwright 同梱の WebKit でも Lax 扱いされなかった。製品版 Safari と Edge は確かめていない。
- 6265bis の「2 minutes」は MAY のモードの中の SHOULD の目安。
- SameSite は「どこから来たか」を site の粒さで見る仕組みで、「本人が望んだか」は見ていない。
自分の現場で確かめる
読んだだけでは身につきません。手元の環境で実際に見てみてください。
理解度チェック
読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。
OWASP の CSRF Prevention Cheat Sheet は、SameSite の限界の1つとして何を挙げていますか。
用語集(4語)
- site
- HTML Standard の定義で (scheme, registrable domain) の組。ポートとサブドメインは比較に入らない。ブラウザの仕組み『分離の単位は origin ではなく site』の scheme + eTLD+1 と同じもの。
- registrable domain(eTLD+1)
- public suffix に左のラベルを1つ足したもの。どこまでが public suffix かは Public Suffix List で決まる。
- Public Suffix List
- com や co.uk のように、登録者が別々になる接尾辞の一覧。どの規則にも当たらないときは既定規則 `*` で最右のラベルを public suffix とする。
- Lax-allowing-unsafe
- 6265bis が認める互換モード。属性なしの Cookie を、トップレベル要求ならメソッドを問わず送る。適用は MAY で、最近作られた Cookie に限るべきとされる。
出典(一次ソース)
- draft-ietf-httpbis-rfc6265bis editor's draft(21 September 2026)§2.3・§4.1.2.7・§5.2・§5.6.7・§5.8.3・§8.8.1・§8.9 ↗
- HTML Standard §7.1.1.1 Sites(Last Updated 22 September 2026) ↗
- URL Standard — registrable domain(Last Updated 10 September 2026) ↗
- Public Suffix List(VERSION 2026-09-23_15-28-19_UTC) ↗
- Public Suffix List wiki — Format(アルゴリズム) ↗
- OWASP Cross-Site Request Forgery Prevention Cheat Sheet(2026-09-11 版) ↗
- Chromium net/cookies/cookie_base.cc(GetEffectiveSameSite、main 8bf6936f) ↗
- Chromium net/cookies/cookie_constants.cc(kLaxAllowUnsafeMaxAge) ↗
- Chrome Platform Status — Cookies default to SameSite=Lax ↗
- Firefox modules/libpref/init/StaticPrefList.yaml(main 529ed25e) ↗