クロスサイト Cookie を明示的にマークする方法を確認して、サイトを保護しましょう。
各 Cookie には Key-Value ペアと、その Cookie が使用されるタイミングと場所を制御するいくつかの属性が含まれています。
SameSite
属性(RFC6265bis で定義)を導入すると、Cookie をファーストパーティ コンテキストと同一サイト コンテキストのどちらに制限するかを宣言できます。ここで「サイト」の意味を正確に理解しておくと役に立ちます。
サイトは、ドメイン サフィックスとその直前のドメイン部分を組み合わせたものです。たとえば、www.web.dev
ドメインは web.dev
サイトの一部です。
これは公開サフィックス リストで定義されるため、.com
などのトップレベル ドメインだけでなく、github.io
などのサービスも含まれます。これにより、your-project.github.io
と my-project.github.io
を別々のサイトとしてカウントできます。
SameSite
属性で Cookie の使用を明示的に示す
Cookie に SameSite
属性を導入すると、3 つの異なる方法でこの動作を制御できます。この属性を指定しないことも、Strict
または Lax
を使用して、Cookie を同一サイトのリクエストに制限することもできます。
SameSite
を Strict
に設定すると、Cookie はファーストパーティ コンテキストでのみ送信されます。ユーザーが使用すると、Cookie のサイトがブラウザの URL バーに現在表示されているサイトと一致する場合にのみ Cookie が送信されます。つまり、promo_shown
Cookie が次のように設定されているとします。
Set-Cookie: promo_shown=1; SameSite=Strict
ユーザーがサイトにアクセスすると、リクエストとともに Cookie が想定どおり送信されます。ただし、他のサイトからのリンクや友人からのメールなど、自分のサイトにアクセスした場合には、最初のリクエストでは Cookie は送信されません。これは、パスワードの変更や購入など、常に最初のナビゲーションの背後にある機能に関連する Cookie があるものの、promo_shown
に対して制限が多すぎる場合に便利です。読者がこのリンクをたどってサイトにアクセスする場合、設定を適用するために Cookie が送信されることを望みます。
このような場合に SameSite=Lax
を使用するのは、トップレベル ナビゲーションで Cookie を送信できるようにすることです。先ほど、別のサイトがコンテンツを参照している cat 記事の例をもう一度見てみましょう。あなたの猫の写真を直接利用し、元の記事へのリンクを提供します。
<p>Look at this amazing cat!</p>
<img src="https://blog.example/blog/img/amazing-cat.png" />
<p>Read the <a href="https://blog.example/blog/cat.html">article</a>.</p>
Cookie は次のように設定されています。
Set-Cookie: promo_shown=1; SameSite=Lax
読者がブログを閲覧していて、ブラウザが amazing-cat.png
をリクエストしても Cookie は送信されません。ただし、読者がブログの cat.html
へのリンクをたどると、そのリクエストに Cookie が含まれます。そのため、サイトの表示に影響する Cookie には Lax
が適しています。ユーザーの操作に関連する Cookie には Strict
が適しています。
最後に、値を指定しなくても、すべてのコンテキストで Cookie を送信するように暗黙的に指示していました。RFC6265bis の最新ドラフトでは、新しい値 SameSite=None
を導入することで、このことが明示されています。つまり、None
を使用することで、サードパーティのコンテキストで Cookie を意図的に送信したいということを明確に伝えられます。

None
、Lax
、Strict
として明示的にマークします。
SameSite を使用しないデフォルトの動作の変更
SameSite
属性は広くサポートされていますが、残念ながらデベロッパーには広く採用されていません。すべての場所に Cookie を送信するというオープンなデフォルト設定により、すべてのユースケースは機能しますが、ユーザーは CSRF や意図しない情報漏洩に対して脆弱になります。デベロッパーが意図を明示し、ユーザーに安全なエクスペリエンスを提供するために、IETF の提案である Incrementally Better Cookie では、次の 2 つの重要な変更点について説明しています。
SameSite
属性のない Cookie はSameSite=Lax
として扱われます。SameSite=None
を持つ Cookie は、Secure
も指定する必要があります。つまり、安全なコンテキストが必要です。
Chrome バージョン 84 では、このデフォルトの動作が実装されています。
Firefox では Firefox 69 でテストできるようになっていますが、将来的にはデフォルトの動作になります。Firefox でこれらの動作をテストするには、about:config
を開き、network.cookie.sameSite.laxByDefault
を設定します。Edge では、デフォルトの動作も変更される予定です。
デフォルトは SameSite=Lax
Set-Cookie: promo_shown=1
SameSite
属性を指定せずに Cookie を送信すると...
Set-Cookie: promo_shown=1; SameSite=Lax
ブラウザでは、その Cookie は SameSite=Lax
が指定されているものとして扱われます。
これはより安全なデフォルトを適用することを目的としていますが、ブラウザに依存して適用するのではなく、明示的な SameSite
属性を設定することをおすすめします。これにより、Cookie の意図が明示され、ブラウザ間で一貫したエクスペリエンスが得られる可能性が高まります。
SameSite=None
は安全である必要があります
Set-Cookie: widget_session=abc123; SameSite=None
Secure
を指定せずに Cookie を設定すると拒否されます。
Set-Cookie: widget_session=abc123; SameSite=None; Secure
SameSite=None
は Secure
属性と必ずペア設定してください。
この動作をテストするには、Chrome 76 以降では about://flags/#cookies-without-same-site-must-be-secure
を有効にします。Firefox 69 以降の場合は、about:config
で network.cookie.sameSite.noneRequiresSecure
を設定します。
有効期限が近づいていない場合でも、新しい Cookie を設定するときに適用し、既存の Cookie を積極的に更新します。
どちらの変更も、以前のバージョンの SameSite
属性を正しく実装しているか、まったくサポートしていないブラウザに対しては下位互換性があります。この変更を Cookie に適用すると、ブラウザのデフォルトの動作に依存せずに、本来の用途を明示的に示すことができます。同様に、まだ SameSite=None
を認識していないクライアントも、この属性を無視して、この属性が設定されていないものとして処理を続行する必要があります。
SameSite
件のクッキーのレシピ
Cookie を更新して SameSite=None
の変更とブラウザの動作の違いを適切に処理する方法については、フォローアップ記事 SameSite Cookie のレシピをご覧ください。
Lily Chen、Malte Ubl、Mike West、Rob Dodson、Tom Steiner、Vivek Sekhar の協力とフィードバックに感謝します。
Cookie のヒーロー画像(作成者: Pille-Riin Priske、Unsplash)