フェッチ メタデータのリクエストヘッダー

W3C ワーキングドラフト,

この文書の詳細情報
この版:
https://www.w3.org/TR/2025/WD-fetch-metadata-20250401/
最新の公開版:
https://www.w3.org/TR/fetch-metadata/
編集者草案:
https://w3c.github.io/webappsec-fetch-metadata/
以前の版:
履歴:
https://www.w3.org/standards/history/fetch-metadata/
フィードバック:
public-webappsec@w3.org 件名 “[fetch-metadata] … message topic …”(アーカイブ
GitHub
編集者:
(Google Inc.)
参加:
Issue を作成 (オープンな issue)
テスト:
web-platform-tests fetch/sec-metadata/

要約

本書は、サーバーがリクエストの方法や利用される文脈に基づいて対応可否をa priori(事前に)判断できるように十分な情報を提供することを目的とした、一連のフェッチ・メタデータ・リクエストヘッダーを定義します。

この文書の位置付け

このセクションは、本書の公開時点での位置付けについて説明しています。現在のW3C発行物およびこの技術報告書の最新版は、W3C技術報告書インデックス https://www.w3.org/TR/ にて参照できます。

本書はWeb Application Security Working Groupによって、勧告トラックを用いてワーキングドラフトとして公開されました。本書は最終的にW3C勧告となることを意図しています。

(アーカイブ済み)公開メーリングリスト public-webappsec@w3.org投稿手順参照)が本仕様に関する議論推奨先です。 メール送信時は、件名に “fetch-metadata” をできるだけ下記の形式で記載してください: “[fetch-metadata] …コメントの要約…

ワーキングドラフトとしての公開は、W3Cおよびそのメンバーによる支持を意味しません。本書はドラフト文書であり、随時更新、置換、または廃止される可能性があります。作業中文書以外として引用することは適切ではありません。

本書はWeb Application Security Working Groupによって作成されました。

本書は、W3C特許方針の下で活動するグループによって作成されています。 W3Cは、グループ配信物に関連した特許開示の公開リストを管理しており、 そのページには特許開示の方法も記載されています。 実際に必須特許請求項を含む特許を把握している個人は、W3C特許方針第6節に従い情報を開示しなければなりません。

この文書は 2023年11月3日版のW3Cプロセス文書 により管理されています。

1. はじめに

興味深いウェブアプリケーションは、多くの場合、ユーザーに関する機微なデータを開示したり、ユーザーの代理で何らかのアクションを実行したりする可能性のある、多数のウェブで公開されるエンドポイントを持つことになります。ユーザーのブラウザは、それらのエンドポイントへのリクエストを簡単に行うよう誘導でき、その際にはユーザーの周辺認証情報(Cookieやイントラネットでの特権的な立場など)も含まれることから、アプリケーションはこれらのエンドポイントの取り扱いについて、悪用を防ぐために非常に注意深くある必要があります。

注意深くあることは、場合によっては困難(「単純な」CSRFなど)であり、他の場合(クロスサイト検索、タイミング攻撃など)には事実上不可能です。後者のカテゴリには、サーバー側の処理時間に基づくタイミング攻撃や、応答の長さによる測定(ウェブ側タイミング攻撃や受動的なネットワーク攻撃者によるもの)が含まれます。

サーバーが、そのリクエストの仕方に基づいて、応答するかどうかをより賢く判断できれば、こうした攻撃の一部を軽減できるでしょう。例えば、銀行サーバーの「すべてのお金を振り込む」エンドポイントが、imgタグから参照されることや、evil.comから正当なリクエストが発生することは非常に考えにくいでしょう。理想的には、サーバーはこれらのリクエストをアプリケーションバックエンドに処理させることなく、a priori(事前に)拒否できるのが望ましいです。

ここでは、ユーザーエージェントが送信リクエストに追加のコンテキストを付加することで、このような意思決定を可能にする仕組みを説明します。サーバーにフェッチメタデータヘッダーのセットとしてメタデータを渡すことで、アプリケーションは一連の前提条件でリクエストをすばやく拒否できるようになります。この仕組みは、必要に応じてアプリケーション層より上(リバースプロキシやCDNなど)でも適用できます。

1.1.

picture 要素から生成されるリクエストは、以下のHTTPリクエストヘッダーを含みます:

Sec-Fetch-Dest: image
Sec-Fetch-Mode: no-cors
Sec-Fetch-Site: cross-site

ユーザーがページ内リンクをクリックし、https://example.com から https://example.com/ へのトップレベルナビゲーションを行った場合、以下のHTTPリクエストヘッダーが含まれます:

Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1

2. フェッチメタデータヘッダー

以下のセクションでは、いくつかのフェッチメタデータヘッダーを定義します。これらはそれぞれ、リクエストの属性をサーバーに公開します。

2.1. Sec-Fetch-Dest HTTPリクエストヘッダー

Sec-Fetch-Dest HTTPリクエストヘッダーは、リクエストdestinationをサーバーに公開します。これは値がトークンでなければならないStructured Fieldです。[RFC9651] ABNFは次のとおりです:

Sec-Fetch-Dest = sf-token

有効なSec-Fetch-Dest値は、リクエストに対して destinationとして [Fetch]で定義されているものの集合です。

まだ知られていないリクエストタイプとの前方互換性を持たせるため、このヘッダーが無効な値を持つ場合はサーバーは無視するべきです。

// fetch()のdestinationは空文字列
Sec-Fetch-Dest: empty

// <img>のdestinationは"image"
Sec-Fetch-Dest: image

// new Worker()のdestinationは"worker"
Sec-Fetch-Dest: worker

// トップレベルナビゲーションのdestinationは"document"
Sec-Fetch-Dest: document

// <iframe>ナビゲーションのdestinationは"iframe"
Sec-Fetch-Dest: iframe
Sec-Fetch-Destヘッダーをセットするための手順(リクエスト rに対して):
  1. アサート: rurl信頼できるURLである。

  2. headerを、値がトークンであるStructured Fieldとして初期化する。

  3. もしrdestinationが空文字列であれば、 headerの値を文字列 "empty"とする。そうでなければ、headerの値をrdestinationとする。

    注: Fetchの空文字列destinationは、処理の簡便化のため明示的な "empty" トークンにマップされます。

  4. 構造化フィールド値をセットする: `Sec-Fetch-Dest`/headerrヘッダーリストに。

2.2. Sec-Fetch-Mode HTTPリクエストヘッダー

Sec-Fetch-Mode HTTPリクエストヘッダーは、リクエストmodeを サーバーに公開します。これは値がトークンでなければならないStructured Fieldです。[RFC9651] ABNFは次のとおりです:

Sec-Fetch-Mode = sf-token

有効なSec-Fetch-Mode値には、"cors"、"navigate"、 "no-cors"、"same-origin"、 "websocket"が含まれます。知られていないリクエストタイプとの前方互換性のため、このヘッダーが無効な値の場合はサーバーは無視するべきです。

Sec-Fetch-Modeヘッダーをセットするための手順(リクエスト rに対して):
  1. アサート: rurl信頼できるURLである。

  2. header を値がトークンであるStructured Fieldとして初期化する。

  3. headerの値を rmodeに設定する。

  4. 構造化フィールド値をセットする: `Sec-Fetch-Mode`/headerrヘッダーリストに。

2.3. Sec-Fetch-Site HTTPリクエストヘッダー

Sec-Fetch-Site HTTPリクエストヘッダーは、リクエストのイニシエータのオリジンとターゲットのオリジンの関係を公開します。これはStructured Fieldで、その値はトークンです。 [RFC9651] ABNFは次のとおりです:

Sec-Fetch-Site = sf-token

有効なSec-Fetch-Site値には、"cross-site"、"same-origin"、 "same-site"、"none" が含まれます。 前方互換性のため、無効な値の場合はサーバーはこのヘッダーを無視するべきです。

Sec-Fetch-Siteヘッダーをセットするための手順(リクエスト rに対して):
  1. アサート: rurl信頼できるURLである。

  2. header を値がトークンであるStructured Fieldとして初期化する。

  3. headerの値をsame-originに設定する。

  4. もしrがユーザーの明示的な操作によるナビゲーションリクエストである場合 (たとえば、アドレスバーへの直接入力やブックマークのクリック等)、headerの値をnoneに変更する。

    注: このやや不明確なステップの詳細は § 4.3 ユーザーによる直接リクエストを参照してください。

  5. headerの値がnoneでない場合は、 rurl list内の各urlについて:

    1. もしurlroriginsame originであれば、 continue

    2. headerの値をcross-siteに設定する。

    3. もしroriginurloriginsame siteでなければ、break

    4. headerの値をsame-siteに設定する。

  6. 構造化フィールド値をセットする: `Sec-Fetch-Site`/headerrヘッダーリストに。

2.4. Sec-Fetch-User HTTPリクエストヘッダー

Sec-Fetch-User HTTPリクエストヘッダーは、ナビゲーションリクエストがユーザー操作で発生したかどうかを公開します。これはStructured Fieldで、その値はbooleanです。[RFC9651] ABNFは次のとおりです:

Sec-Fetch-User = sf-boolean

注: このヘッダーはナビゲーションリクエスト かつ値がtrueの場合のみ送信されます。 一般的なサブリソースリクエストについても将来的に拡張するのは合理的かもしれませんが、その情報公開によって利便性向上が見込まれるユースケースがあり、かつ全サブリソースリクエストタイプの状態定義方法に合意できれば、検討されるでしょう。当面は、ナビゲーションリクエストの明確なユースケースが存在し、相互運用性の観点で定義しやすいです。

Sec-Fetch-Userヘッダーをセットするための手順(リクエスト rに対して):
  1. アサート: rurl信頼できるURLである。

  2. もしrナビゲーションリクエスト でない、 または ruser-activationfalseの場合は、処理を戻す。

  3. headerStructured Field(値はトークン)として初期化する。

  4. headerの値をtrueとする。

  5. 構造化フィールド値をセットする: `Sec-Fetch-User`/headerrヘッダーリストに。

3. FetchおよびHTMLとの統合

Sec-Fetch-Userをサポートするために、requestuser-activationを持ち、これはHTMLのcreate navigation params by fetchingアルゴリズムにより設定されない限り、false となります。

フェッチメタデータヘッダーは、Fetchの "HTTP-network-or-cache" アルゴリズム内から発信されるリクエストに付加されます。詳細な統合については該当仕様書を参照してください [FETCH]

リクエストにFetchメタデータヘッダーを追加するには、request rを与えて以下の手順によります:
  1. もしrurl信頼できるURLでない場合、処理を戻す。

  2. Sec-Fetch-Destヘッダーをセットする r

  3. Sec-Fetch-Modeヘッダーをセットする r

  4. Sec-Fetch-Siteヘッダーをセットする r

  5. Sec-Fetch-Userヘッダーをセットする r

4. セキュリティおよびプライバシーの考慮事項

4.1. リダイレクト

ユーザーエージェントは、リダイレクトチェーンの各リクエストにSec-Fetch-Siteヘッダーを送信します。クロスオリジンまたはクロスサイトリダイレクトが発生した場合、混乱を避けるためにヘッダーの値が変化します。

Sec-Fetch-Siteヘッダーを設定するアルゴリズムは、requesturl list全体を走査し、リスト内にリクエストのcurrent urlとクロスサイトなURLがあればcross-site、全てが同じサイトならsame-site、全てが同一オリジンならsame-originを送信します。

例えば、https://example.com/https://example.com/redirectをリクエストした場合、最初のSec-Fetch-Sitesame-originになります。このレスポンスがhttps://subdomain.example.com/redirectにリダイレクトした場合、そのリクエストのSec-Fetch-Site値はsame-siteとなります(https://subdomain.example.com/https://example.com/は同じ登録可能ドメイン)。さらにhttps://example.net/redirectにリダイレクトすると、Sec-Fetch-Sitecross-siteになります(https://example.net/は他と同じサイトではないため)。最終的にhttps://example.com/に戻ってきても、リダイレクトチェーンにhttps://example.net/が含まれているため、最終リクエストもcross-siteのままです。

注: Sec-Fetch-Site: none の特別な場合、短縮リンクをアドレスバーにコピー&ペーストするような一般的なケースをサポートするため、リダイレクト経路でもその値を維持するのが合理的です。例えば、ユーザーエージェントが https://sho.rt/linkへのアドレスバーでのナビゲーションにSec-Fetch-Site: noneをつけた場合、リダイレクト先のhttps://target.com/long/path/goes/hereでもSec-Fetch-Site: noneを保持するべきです。

4.2. Sec-プレフィックス

本書で定義されている各ヘッダーは Sec- という接頭辞を持っており、すべて禁止レスポンスヘッダー名となります。これによりJavaScriptからは変更できません。悪意のあるウェブサイトが偽装したメタデータをリクエストに付与させることを防ぐため、サイト運営者はより安心して情報に基づく判断ができるようになります。

4.3. ユーザーによる直接リクエスト

Sec-Fetch-Siteヘッダーを設定する際、ユーザーエージェントは「ユーザーの明示的な操作によって発生したナビゲーションリクエスト」とそれ以外を区別するよう求められます。このやや曖昧な表現はHTMLから引用されており、HTMLでは「ユーザーエージェントは、この仕様で定義されているものに加え、さまざまな方法でユーザー操作により閲覧コンテキストをナビゲートさせることができる」と示唆されています。

目標は、「ウェブ側で制御されたナビゲーション」(例: リンク、window.locationの設定、フォーム送信等)と、そうでないもの(例: アドレスバーやブックマーク等のユーザーエージェントUI操作)を区別することです。前者にはSec-Fetch-Siteヘッダーに適切な値(same-originsame-sitecross-site)を付与し、後者はnoneとします。これは、特定のサイトが実際にリクエストを引き起こしていないことを示し、サーバー側で信頼できる操作として扱うことに意味があります。

各ユーザーエージェントには、それぞれ独自の分類基準があるかもしれません。またこれらケースに対する自動試験スイートを共有するのは難しいでしょう。それでも一般化しやすい動作については足並みを揃えるのが理想です。以下にいくつかの例を示します:

4.4. 拡張機能によるリクエスト

一部のユーザーエージェントは、拡張機能が通常のWebコンテンツよりもユーザーのWeb体験をコントロールできるように特権的なリクエスト送信をサポートしています。これらはWebプラットフォームの範囲外ですが、ユーザーエージェントにはそのようなリクエストをサーバーにどう表現するかを慎重に検討することを推奨します。一般に、以下2つの目標を満たすのが理想です:

  1. 特別な権限がない拡張機能は、そのサイトのFetch Metadataロジックを迂回できるリクエストを送出できないようにする。

  2. 開発者が拡張機能によるリクエストを識別し、サーバー側のFetch Metadataロジックから除外するかどうかを制御できるようにする。これにより、Fetch Metadata保護を自信を持って導入しつつ正当なユーザー利便を損なうリスクを低減できます。

これらの目標のもと、ユーザーエージェントは以下の動作を実装することが推奨されます:

  1. 拡張機能が特定URLへのアクセス権を持たない場合、そのリクエストには通常のWebリクエスト同様 Sec-Fetch-Site: cross-site を付与することができます。権限がある場合は Sec-Fetch-Site: same-origin とすることができます。

  2. 拡張機能からの送信リクエストにはOriginヘッダーを含め、その値は実装依存としサーバーがWeb由来か拡張由来か判別できるようにします。

5. 導入上の注意点

5.1. Vary(可変)

特定のエンドポイント応答がクライアントから渡されるFetchメタデータヘッダーの値に依存する場合、開発者はキャッシュが正しく処理できるよう適切な Vary ヘッダーを含めるよう注意してください [RFC9110]。例: Vary: Accept-Encoding, Sec-Fetch-Site

5.2. ヘッダー肥大化

以前のバージョンでは、内容がディクショナリ型の Sec-Metadata ヘッダー1つにまとめていました。その後の議論(およびMark Nottinghamによる [mnot-designing-headers])を経て、ひとつのディクショナリ型からシンプルなトークンだけを持つ複数のヘッダーに変更しています。この設計は、HTTPの現行HPACK圧縮アルゴリズムの下で大幅に効率的です。

この話題の詳細は w3ctag/design-reviews#280 のレビューで議論されています。

6. IANA 関連事項

恒久的メッセージヘッダーフィールドレジストリは、Fetchメタデータヘッダー登録にあたって以下の内容で更新されるべきです:[RFC3864]

6.1. Sec-Fetch-Dest 登録

ヘッダーフィールド名

Sec-Fetch-Dest

該当プロトコル

http

ステータス

standard

著者/変更管理者

Me

仕様文書

本仕様(§ 2.1 Sec-Fetch-Dest HTTPリクエストヘッダー参照)

6.2. Sec-Fetch-Mode 登録

ヘッダーフィールド名

Sec-Fetch-Mode

該当プロトコル

http

ステータス

standard

著者/変更管理者

Me

仕様文書

本仕様(§ 2.2 Sec-Fetch-Mode HTTPリクエストヘッダー参照)

6.3. Sec-Fetch-Site 登録

ヘッダーフィールド名

Sec-Fetch-Site

該当プロトコル

http

ステータス

standard

著者/変更管理者

Me

仕様文書

本仕様(§ 2.3 Sec-Fetch-Site HTTPリクエストヘッダー参照)

6.4. Sec-Fetch-User 登録

ヘッダーフィールド名

Sec-Fetch-User

該当プロトコル

http

ステータス

standard

著者/変更管理者

Me

仕様文書

本仕様(§ 2.4 Sec-Fetch-User HTTPリクエストヘッダー参照)

7. 謝辞

この仕組みの設計にあたり、多大なご助力をいただいたAnne van Kesteren、Artur Janc、Dan Veditz、Łukasz Anforowicz、Mark Nottingham、Roberto Clapis各氏に感謝します。

適合性

文書規則

適合性要件は、記述的な断定とRFC 2119の用語の組み合わせで表現されます。 本仕様の規範的部分における“MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、 “MAY”、“OPTIONAL”というキーワードはRFC 2119に記された定義に従って解釈されます。 ただし、可読性を優先し、この仕様ではこれらの語句はすべて大文字では記述されていません。

明示的に非規範的と記載されている節、例、注記を除き、本仕様のすべての本文は規範的です。[RFC2119]

本仕様書における例は「例えば」などで導入されるか、または class="example" で表示されます。たとえば以下のようになります:

これは参考例の例です。

参考注記は「注:」で始まり、class="note"で規範本文と区別されます。例えば:

注: これは参考注記です。

適合するアルゴリズム

アルゴリズムの一部として命令形で表現された要件(たとえば「先頭の空白文字をすべて取り除く」や「これらのステップを中止してfalseを返す」など)は、その導入で用いられているキーワード("must"、"should"、"may"など)の意味で解釈されます。

アルゴリズムや具体的な手順として表現されている適合要件は、その結果が同等である限り、どのような方法でも実装できます。 とりわけ、本仕様で定義されているアルゴリズムは理解しやすさを重視したものであり、性能を意識した設計ではありません。 実装者は最適化を推奨されます。

索引

本仕様で定義されている用語

参照文献で定義されている用語

参考文献

標準的参考文献

[FETCH]
Anne van Kesteren. Fetch Standard. Living Standard. URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC3864]
G. Klyne; M. Nottingham; J. Mogul. Registration Procedures for Message Header Fields. September 2004. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc3864
[RFC9651]
M. Nottingham; P-H. Kamp. Structured Field Values for HTTP. September 2024. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9651
[SECURE-CONTEXTS]
Mike West. Secure Contexts. 10 November 2023. CRD. URL: https://www.w3.org/TR/secure-contexts/
[URL]
Anne van Kesteren. URL Standard. Living Standard. URL: https://url.spec.whatwg.org/

参考情報

[MNOT-DESIGNING-HEADERS]
Mark Nottingham. Designing Headers for HTTP Compression. URL: https://www.mnot.net/blog/2018/11/27/header_compression
[RFC9110]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. HTTP Semantics. June 2022. Internet Standard. URL: https://httpwg.org/specs/rfc9110.html
MDN

Headers/Sec-Fetch-Dest

In all current engines.

Firefox90+Safari16.4+Chrome80+
Opera?Edge80+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera MobileNone
MDN

Headers/Sec-Fetch-Mode

In all current engines.

Firefox90+Safari16.4+Chrome76+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Headers/Sec-Fetch-Site

In all current engines.

Firefox90+Safari16.4+Chrome76+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Headers/Sec-Fetch-User

In all current engines.

Firefox90+Safari16.4+Chrome76+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?