ブログやヘルプページを外部のサービスで運用し、blog.example.comのようなサブドメインでつなぐ構成はよくあります。DNSにレコードを1行足すだけで公開できて便利ですが、このとき本体サイトのCookieがどこまで届くのかは見落とされがちです。この記事では、CookieのDomain属性の仕組みと、サブドメインを外部に向けるときの設計の考え方をまとめます。
この記事は2026年10月時点のMDN・RFC 6265・Cloudflare公式ドキュメントの記述をもとにしています。例はすべて架空の構成です。
結論:Domain属性付きのCookieは、外部に向けたサブドメインにも届く
先に結論です。
Domain=example.comのようにDomain属性を付けて発行したCookieは、blog.example.comなどのすべてのサブドメインにも送られます。Domain属性を付けずに発行したCookieはホスト専用になり、サブドメインには送られません。- そのため、本体サイトが
Domain属性付きのCookieを使っていると、サブドメインを外部サービスに向けた時点で、そのCookieが外部サービスにも届きます。 - 根本対策はCookieの発行範囲を絞ることです。すぐに変えられない場合は、CDNのプロキシを通してエッジでCookieを削除する方法がありますが、外部サービスがプロキシ経由に対応しているかの確認が必要で、防げる範囲にも限りがあります。
前提知識:Domain属性とホスト専用Cookie
CookieはサーバーがSet-Cookieヘッダーで発行します。Domain属性の有無で、送られる範囲が変わります。
# ① Domain 属性あり:example.com とすべてのサブドメインに送られる
Set-Cookie: session=abc123; Domain=example.com; Secure; HttpOnly
# ② Domain 属性なし:発行したホスト(www.example.com)だけに送られる
Set-Cookie: session=abc123; Secure; HttpOnly
MDNでは、Domainを指定するとそのドメインとすべてのサブドメインで使えるようになり、省略すると発行したホストだけに返される「ホスト専用Cookie」になると説明されています。指定した場合、サブドメインを除外する方法はありません。
また、.example.comのように先頭にドットを付けても、今の仕様では無視されます。Domain=example.comとDomain=.example.comは同じ意味です。
どんなときに問題になるか
架空の構成で考えます。
| ホスト | 運用 | 備考 |
|---|---|---|
www.example.com |
自社のアプリケーション | ログイン用CookieをDomain=example.comで発行 |
blog.example.com |
外部のホスティングサービス | DNSのCNAMEで外部に向けている |
ユーザーがログインしたままblog.example.comを開くと、ブラウザはDomain=example.comのCookieをリクエストに付けて外部サービスへ送ります。ブラウザは「その先を誰が運用しているか」を考慮しません。ホスト名が条件に合えば送ります。
この状態には、次のリスクがあります。
- Cookieが外部サービスに渡る:外部サービスのアクセスログなどに、本体サイトのセッション情報が残る可能性があります。
- サブドメイン側からCookieを上書きされる:サブドメインは、親ドメイン(
Domain=example.com)向けのCookieを発行できます。外部サービス側の設定ミスなどで、本体サイトのCookieと同じ名前のCookieを発行して上書きしたり、紛れ込ませたりできるため、本体サイトの動作に影響します。 - ページ内のスクリプトから読まれる:
Domain属性付きで、HttpOnlyが付いていないCookieは、サブドメインのページで動くJavaScriptからも読めます。
確かめ方:開発者ツールで2か所を見る
- 本体サイトの
Set-Cookie:ブラウザの開発者ツールのNetworkタブで、ログイン時などのレスポンスヘッダーを開き、Set-CookieにDomain=が含まれているかを確認します。 - サブドメインへのリクエスト:本体サイトにログインした状態で
blog.example.comを開き、リクエストヘッダーのCookieに本体サイトのCookieが入っていないかを確認します。
コマンドで発行内容を確認することもできます。
curl -s -o /dev/null -D - https://www.example.com/login | grep -i '^set-cookie'
対策1:Cookieの発行範囲を絞る(根本対策)
サブドメイン間でCookieを共有する必要がないなら、Domain属性を外してホスト専用にするのが根本対策です。外部サービスにはそもそも送られなくなります。
ただし、Domain属性を外すだけでは、リスク2は防げません。サブドメインは引き続きDomain=example.comで同じ名前のCookieを発行できるためです。するとwww.example.comには同じ名前のCookieが2つ届き、サーバーが外部側の値を読んでしまうことがあります(Cookie Tossingと呼ばれます)。
そこで、Cookie名に__Host-接頭辞を付けます。__Host-が付いたCookieは、Secureが必須で、Path=/で、Domain属性を付けられないというルールをブラウザが強制します。Domain付きで発行できないので、サブドメインから同じ名前のCookieを紛れ込ませることもできなくなります。リスク2まで防ぐなら、__Host-を付けてください。
Set-Cookie: __Host-session=abc123; Path=/; Secure; HttpOnly; SameSite=Lax
Cookie名を変えると既存のログイン状態が切れるので、切り替えのタイミングは計画して行ってください。
対策2:CDNのプロキシを通し、エッジでCookieを削除する
認証基盤の都合などで、すぐには発行範囲を変えられないこともあります。その場合、サブドメインへのリクエストをCDNのプロキシ経由にして、外部サービスに転送する前にCookieヘッダーを削除する方法があります。
Cloudflareなら、DNSレコードをProxiedにしたうえで、Request Header Transform RulesでCookieヘッダーを削除します。公式ドキュメントでは、Cookieヘッダーの値の変更はできないものの、削除はできると案内されています。
- 対象:ホスト名が
blog.example.comと一致するリクエスト - 操作:
Cookieヘッダーを削除(Remove)
同様に、Response Header Transform Rulesで外部サービスからのSet-Cookieを削除すれば、リスク2の「上書き」も防げます(外部サービスがCookieを使っている場合は、その機能が動かなくなる点に注意してください)。
ただし、この方法には限界があります。
- 外部サービスがプロキシ経由に対応している必要があります。Cloudflareの公式ドキュメントでも、SaaSのホスティングサービスや他のCDNに向けたレコードをプロキシすると、SSLエラーやリダイレクトのループが起きることがあると案内されています。事前に外部サービスのドキュメントで、CDNプロキシ経由の利用が想定されているかを確認してください。
- エッジで削除できるのはリクエストヘッダーとレスポンスヘッダーだけです。ページ内のJavaScriptが
document.cookieで読み書きすること(リスク3)は防げません。
あくまで一時的な対策として使い、対策1に移ることをおすすめします。
DNS-onlyとプロキシの使い分け
| レコードの用途 | 推奨 | 理由 |
|---|---|---|
| 自社で運用するWebサイト | プロキシ | DDoS対策・キャッシュ・ヘッダー制御が使える |
| 外部サービスに向けたサブドメイン | サービスが対応していればプロキシ、していなければDNS-only | 二重のTLS終端などで動かないことがある |
| ドメイン所有確認・証明書発行の検証用CNAME | DNS-only | プロキシするとCNAMEの向き先ではなくCloudflareのIPが返り、検証に失敗する |
| メール(MXなど) | DNS-only | MXはそもそもプロキシできない |
検証用のレコードは、プロキシを通すと外部サービスが正しい値を受け取れず、検証が失敗します。サービスによっては、検証後もずっとDNS-onlyにしておく必要があります。
チェックリスト:サブドメインを外部に向ける前に
- 本体サイトの
Set-CookieにDomain=が含まれていないか Domain属性付きのCookieがある場合、本当にサブドメイン間で共有する必要があるか- 重要なCookieに
HttpOnlyとSecureが付いているか - ログイン用など重要なCookieに
__Host-接頭辞を付けているか - 外部サービスはCDNプロキシ経由の利用に対応しているか
- 所有確認・証明書の検証用レコードをDNS-onlyにしているか
- 公開後、ログインした状態でサブドメインを開き、リクエストの
Cookieヘッダーを確認したか
よくある質問
Q. SameSite=Strictを付ければ、サブドメインには送られませんか?
A. 送られます。SameSiteは「別のサイトから来たリクエストに付けるか」を決める属性です。www.example.comとblog.example.comは同じサイトとして扱われるため、SameSiteでは防げません。
Q. サブドメインではなく、別のドメインにすれば安全ですか?
A. Cookieの送信範囲という点では安全です。example-blog.comのように別のドメインにすれば、example.comのCookieは送られません。ブランドやSEOの都合と合わせて検討してください。
Q. 外部サービスが信頼できるなら、気にしなくてよいですか?
A. 運営元が信頼できても、ログの扱い・設定ミス・将来の仕様変更までは制御できません。渡す必要のない情報は渡さない設計にしておくのが安全です。
まとめ
Domain属性付きのCookieは、すべてのサブドメインに送られる。運用者が誰かは関係ないDomain属性を付けなければホスト専用になる。ただしそれだけではサブドメインからの上書きは防げないので、__Host-接頭辞まで付ける- 根本対策はCookieの発行範囲を絞ること
- CDNのエッジで
Cookieを削除する方法は、外部サービスの対応状況を確認したうえでの一時対策。JavaScriptからの読み取りは防げない - 所有確認・証明書の検証用レコードはDNS-onlyにする
サブドメインを追加する前に、一度Set-Cookieを確認してみてください。
参考
- Set-Cookie header – MDN Web Docs
- Site – MDN Web Docs Glossary
- RFC 6265: HTTP State Management Mechanism
- Request Header Transform Rules – Cloudflare Docs
- Response Header Transform Rules – Cloudflare Docs
- Proxy status – Cloudflare Docs
- Proxy status: Use cases – Cloudflare Docs
