Referrer-Policy の値ごとに Referer に入るもの:完全な URL、オリジンだけ、何もなし

リンクをたどるときや画像を読み込むときに、ブラウザが Referer に何を入れるかは Referrer-Policy で決まります。8 つの値の違い、URL から必ず削られる部分、ヘッダー・meta・属性の関係、リダイレクトと Origin ヘッダーへの影響を仕様に沿って整理しました。

開発Webセキュリティプライバシー

パスワード再設定ページの URL が https://example.com/account/reset?token=8f3a だとします。このページに外部のヘルプへのリンクや別ドメインの画像が 1 つでもあれば、ブラウザはそのリクエストの Referer ヘッダーに今のページの URL を入れて送ることがあります。クエリ文字列のトークンも含めてです。W3C の Referrer Policy 仕様は、冒頭でまさにこうした例を挙げています。URL にセッション識別子を含む HTTPS アプリケーションと、URL そのものが権限になる「capability URL」です。

Referrer-Policy は、このヘッダーに何を入れるかを決めるルールです。結果は次の 3 つのどれかになります。一部を削った完全な URL、オリジンだけ、ヘッダーなし。

どのポリシーでも削られる部分

どのポリシーでも、URL がそのまま送られることはありません。Referrer Policy 8.4 節の「strip url」アルゴリズムは次を取り除きます。

  • フラグメント(# 以降)
  • ユーザー名とパスワード(https://user:pass@host/ の user:pass)

RFC 9110 の 10.1.3 節も同じことを求めています。ユーザーエージェントは Referer の値を作るとき、フラグメントと userinfo を含めてはなりません(MUST NOT)。また同じアルゴリズムは、元の URL のスキームがローカルスキームならリファラーそのものを作りません。

「オリジンだけ」を送るポリシーは、さらにパスとクエリも削ります。残るのはスキーム、ホスト、ポートで、ブラウザは有効な URL になるよう末尾に / を付けます。そのため、オリジンだけを送ると値は https://example.com/ になります。

逆に「完全な URL」ではパスとクエリ文字列が残ります。冒頭の例なら https://example.com/account/reset?token=8f3a がそのまま送られます。削られるのはフラグメントだけです。

8 つの値

https://example.com/page?q=1 の文書から 3 か所にリクエストを送るとき、各ポリシーの結果は次のとおりです。Referrer Policy 8.3 節の「Determine request’s Referrer」アルゴリズムと 3 章の例に沿っています。

ポリシー 同一オリジン https://example.com/other 別オリジン https://not.example.com/ HTTPS から HTTP へ http://not.example.com/
no-referrer なし なし なし
no-referrer-when-downgrade 完全な URL 完全な URL なし
same-origin 完全な URL なし なし
origin オリジン オリジン オリジン
strict-origin オリジン オリジン なし
origin-when-cross-origin 完全な URL オリジン オリジン
strict-origin-when-cross-origin 完全な URL オリジン なし
unsafe-url 完全な URL 完全な URL 完全な URL

名前の strict- は最後の列に関わります。仕様の条件は「TLS で保護された文書から、potentially trustworthy(潜在的に信頼できる)URL ではない宛先へのリクエスト」で、仕様の例では http:// のアドレスがこれに当たります。このとき strict- 系と no-referrer-when-downgrade は何も送りません。元の文書が最初から HTTP ならこの条件に当たらないので、たとえば strict-origin はどこへでもオリジンを送ります。

見落としやすい点もあります。

  • 同一オリジンかどうかは、リクエストのオリジンと、リクエストがいま向かっている URL のオリジンを比べて判断します。origin-when-cross-origin の節の注記は、http://example.com/ から https://example.com/ のようにスキームが上がるだけでも別オリジンのリクエストとみなすと書いています。
  • 10.1 節は、origin、origin-when-cross-origin、unsafe-url が安全なサイトのオリジンや URL を暗号化されていない通信で漏らしうると書いています。unsafe-url について仕様は「名前は嘘をつかない」とまで注意しています。
  • strict-origin は同一オリジンのリクエストでもオリジンしか送りません。サイト内のどのページから来たかを知りたい場合には向きません。

ポリシーを決める場所

Referrer Policy 4 章は、リクエストのポリシーが決まる経路を 5 つ挙げています。

  1. レスポンスヘッダー Referrer-Policy
  2. <meta name="referrer" content="...">
  3. a、area、img、iframe、link 要素の referrerpolicy 属性
  4. a、area、link 要素の rel="noreferrer"
  5. 継承(srcdoc の iframe や blob URL から作られたコンテキスト)

ヘッダー名は Referer の綴り間違いを引き継いでいません。ポリシーのヘッダーは Referrer-Policy、リクエストヘッダーは Referer です。

fetch() ではリクエストごとに指定できます。Fetch Standard の Request コンストラクターは referrerPolicy オプションをそのままリクエストのポリシーにし、referrer: "" を渡すとリクエストのリファラーを no-referrer にします。

// このリクエストではオリジンだけを送る
await fetch("https://api.partner.example/v1/items", {
  referrerPolicy: "strict-origin",
});

// このリクエストでは Referer を送らない
await fetch("https://cdn.partner.example/pixel.gif", { referrer: "" });

要素の属性や fetch() のオプションで何も指定していないリクエストのポリシーは空文字列です。現在の Fetch Standard の main fetch アルゴリズムは、この空の値をリクエストの policy container が持つポリシーで埋めます。Referrer Policy 6 章は、HTML Standard が文書のレスポンスからポリシーを決めてその文書に持たせ、その文書から出るリクエストの基準にすると説明しています。つまり個々のリクエストで指定しなければ、文書のポリシーが使われます。

ヘッダーに値を複数書くと

8.1 節は Referrer-Policy ヘッダーのトークンを先頭から読み、認識できる値が出るたびにポリシーを上書きします。知らない値は読み飛ばします。そのため最後に認識された値が勝ちます。11.1 節はこれを新しい値を展開する方法として説明しています。先頭に古いブラウザも知っている値を置き、後ろに新しい値を置きます。

Referrer-Policy: no-referrer, strict-origin-when-cross-origin

新しい値を知っているブラウザは後ろの値を使い、知らないブラウザは前の値のままになります。ただし仕様は、この動作が referrerpolicy 属性には当てはまらないと明記しています。属性については、スクリプトで値を設定して読み戻せば、その値に対応しているか確かめられると案内しています。

リダイレクトのレスポンスヘッダーもポリシーを変える

Fetch Standard の HTTP-redirect fetch は、リダイレクトをたどる前に Referrer Policy の「Set request’s referrer policy on redirect」を呼びます。このアルゴリズムはリダイレクトのレスポンスの Referrer-Policy ヘッダーを 8.1 節と同じ方法で解釈し、結果が認識できる値で、かつ空文字列でないときだけリクエストのポリシーを置き換えます。ヘッダーがない、または知らない値しかなければ、ポリシーはそのままです。

ここで大事なのは、新しいポリシーが何に適用されるかです。main fetch は最初のリクエストを送る前にリクエストのリファラーを計算し、その結果をリクエストに保存します。リダイレクトをたどるときは同じリクエストで main fetch がもう一度走り、リファラーがすでに no-referrer なら計算を飛ばし、URL なら最初の段階で保存されたその値を新しいポリシーでもう一度削ります。

そのためリダイレクトは、残っている情報をどこまで送るかは変えられても、すでに削られた情報を元に戻すことはできません。

  • no-referrer で送ったリクエストは、最初からリファラーが no-referrer です。リダイレクトのレスポンスが Referrer-Policy: unsafe-url を返しても Referer は生まれません。
  • 最初の段階でオリジンだけが残ったなら、パスとクエリはもう消えています。後の段階でポリシーが緩くなっても、送れるのはそのオリジンまでです。
  • 最初の段階で完全な URL が残ったなら、たとえば strict-origin-when-cross-origin で同一オリジンに送ったリクエストなら、リダイレクトのレスポンスが unsafe-url を指定して別オリジンへ転送したとき、その完全な URL が別オリジンに届きます。10.2 節は、より緩いポリシーへ変えることを禁じていないと述べています。

逆に、短縮 URL やログインの中継のようにリダイレクトを自分のサーバーが返すなら、そのレスポンスに厳しいポリシーを付けて次のリクエストに載る値を減らせます。リダイレクトのステータスコードそのものは HTTP リダイレクトの記事で扱いました。

Origin ヘッダーにも影響する

Referrer-Policy が変えるのは Referer だけではありません。Fetch Standard 3.2 節の「append a request Origin header」アルゴリズムは、リクエストを次の順に確かめます。

  1. リクエストの response tainting が cors か、モードが websocket または webtransport なら、オリジンをそのまま付け、ポリシーは見ません。main fetch は、cors モードで別オリジンへ送るリクエスト、たとえば別オリジンへの fetch() の response tainting を cors にします。
  2. それ以外で GET か HEAD のリクエストには、このアルゴリズムは Origin を付けません。
  3. それ以外でも、モードが cors ならポリシーを見ずにオリジンをそのまま付けます。同一オリジンへの fetch() の POST がこれに当たります。fetch() の既定のモードは cors で、同一オリジンのリクエストの response tainting は basic のままだからです。
  4. 残りのリクエスト、たとえば navigate や no-cors モードのリクエストでは、ポリシーによって Origin が null になります。
    • no-referrer:常に null
    • no-referrer-when-downgrade、strict-origin、strict-origin-when-cross-origin:HTTPS のオリジンから HTTPS ではない URL へ向かうとき null
    • same-origin:別オリジンへ向かうとき null

サーバーが CSRF 対策として Origin を確認している場合、サイト全体に no-referrer を設定すると、GET でも HEAD でもなく、すでに navigate モードのリクエストは 4 番目のポリシー分岐に進み、no-referrer ではその分岐が Origin を null にします。同じポリシーでも、同一オリジンへの fetch() の POST は実際のオリジンを送ります。このアルゴリズムの注記は、CORS プロトコルのようにオリジンの共有を明示的に選んでいないすべてのリクエストでリファラーポリシーが考慮されると説明しています。CORS と Origin の関係は CORS プリフライトの記事にまとめました。

デフォルト値はどこで決まるか

どこでもポリシーを決めていなければ、ブラウザのデフォルトが使われます。ただ、そのデフォルトを確認すべき文書は変わっています。

  • https://www.w3.org/TR/referrer-policy/ にある W3C の文書は 2017 年 1 月 26 日付の Candidate Recommendation です。この版は空のポリシーを no-referrer-when-downgrade として扱うと書いています。
  • 2026 年 10 月 6 日付の Fetch Standard は、空のポリシーを HTML Standard の policy container の値で埋め、Referrer Policy の参照先として https://w3c.github.io/webappsec-referrer-policy/ を指しています。

つまりいまの Fetch が従うデフォルトは、2017 年の版ではなく HTML Standard と Fetch が指す版の側で決まります。そのためこの記事では、2017 年版のデフォルトを今のブラウザの動作としては紹介しません。実務でやることは単純で、デフォルトに頼らずレスポンスヘッダーでポリシーを明示すれば済みます。motitory.com は public/_headers で、すべての静的レスポンスに Referrer-Policy: strict-origin-when-cross-origin を付けています。

値を選ぶときは、次を目安にできます。

  • URL にトークンや個人を特定できる情報が入るページ:no-referrer か same-origin。サイト内の分析が必要なら same-origin が合います。
  • 一般的なページ:strict-origin-when-cross-origin が無難です。同一オリジンには完全な URL、別オリジンにはオリジンだけ、HTTP には何も送りません。
  • unsafe-url、origin、origin-when-cross-origin は、HTTPS のページの情報が HTTP のリクエストに載りうるので、はっきりした理由があるときだけ使います。

ポリシーで防げないこと

  • Referrer-Policy は送る側の約束です。Referrer Policy 9.1 節はユーザーエージェントがリファラーを止める選択肢をユーザーに提供してよいとし、Fetch Standard も注記で同じことを書いています。RFC 9110 は Referer を無差別に削除する中継装置があるとも書いています。サーバーは Referer がない、または短くなったリクエストも処理できるようにし、アクセス制御を Referer に任せてはいけません。RFC 9110 も、すべてのリクエストにこのヘッダーがあるわけではないと書いています。
  • 1.2 節は、capability URL はリファラー以外の経路でも漏れうるし、リファラーを制御するだけではそのすべてを防げないと注記しています。RFC 9110 の 17.9 節は、そもそも機密性のある値を URI に入れない方法を勧めています。フォームで POST を使う、URI を作る前に値を変換する、サーバーが作った別の URI にリダイレクトする、といった方法です。

参考にした文書

2026 年 10 月 18 日にリンクと内容を確認しました。Fetch Standard は随時更新される文書なので、上の内容はこの日に取得した版に基づいています。

ブログへ