ユーザーエージェント クライアントヒント

ドラフト コミュニティグループレポート,

このバージョン:
https://wicg.github.io/ua-client-hints/
編集者:
(Google LLC)
(Google LLC)
元編集者:
(Google LLC)
参加方法:
課題を提出 (オープン課題)

概要

本ドキュメントは、開発者が必要に応じてエージェントベースのコンテンツネゴシエーションを行えるようにするクライアントヒントのセットを定義します。同時に、伝統的な User-Agent ヘッダーによって露呈される過去の問題やパッシブフィンガープリントの表面を回避します。

この文書のステータス

この仕様はWeb Platform Incubator Community Groupによって公開されました。 W3C標準でもW3C標準化トラック上のものでもありません。 W3C Community Contributor License Agreement (CLA)のもと、限定的なオプトアウトや他の条件が適用されることにご注意ください。 W3Cコミュニティおよびビジネスグループについて詳しくは、こちらをご覧ください。

1. はじめに

このセクションは規範的ではありません.

現在、ユーザーエージェントは通常、各リクエストとともに User-Agent HTTPリクエストヘッダーフィールドをサーバーに送信して自身を識別します([rfc9110]のSection 5.5.3で定義)。理想的には、このヘッダーによってサーバーはコンテンツネゴシエーションができ、特定のユーザーエージェントに最適なリソースを送信し、帯域幅やユーザー体験を最適化できます。しかし実際には、このヘッダーの値はデフォルトとしては不適切なほど多くのユーザーのデバイス情報を露出する一方で、誤ったサーバー側のヒューリスティクスを回避するためにユーザーエージェントを意図的に偽装することもあります。

例えば、iOS版Chromeの最近のバージョンは次のように自身を識別します:

User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X)
            AppleWebKit/605.1.15 (KHTML, like Gecko)
            CriOS/69.0.3497.105 Mobile/15E148 Safari/605.1

一方、Edgeの最近のバージョンは次のように自身を識別します:

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
            AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.2704.79
            Safari/537.36 Edge/18.014

これらの文字列には多くの情報(そしてかなりの虚偽情報)が詰め込まれています。バージョン番号、プラットフォームの詳細、モデル情報などがすべてリクエストごとに送信され、様々なフィンガープリンティング手法の基盤となっています。各ベンダーは自身のユーザーエージェント文字列の変更を試みてきましたが、歴史的な手法を妨げてきた開発者からのフィードバックにはいくつかのカテゴリがあります:

  1. ブランドとバージョン情報(例: "Chrome 69")により、Webサイトは特定のリリースに存在する既知のバグを回避することができます。例えばContent Security Policyの実装はベンダーごとに大きく異なり、どのブラウザがパースと実行を担当するかを知らずにHTTPレスポンスにどのポリシーを送るべきか判断するのは困難です。

  2. 開発者はしばしばユーザーエージェントやプラットフォームに基づいて送信するコンテンツをネゴシエートします。例えば、あるアプリケーションフレームワークは、iOS上のアプリをAndroid上の同じアプリとは異なるスタイルにして、それぞれのプラットフォームの美学やデザインパターンに合わせます。

  3. #1と同様に、OSのリビジョンやアーキテクチャが特定のバグの原因となり得るため、Webサイトのコードで回避策を取ることができ、ダウンロードする適切な実行ファイル(32bit/64bit、ARM/Intelなど)選択にも有用です。

  4. 高度な開発者はモデルやメーカー情報を使ってデバイスの能力(例: [FacebookYearClass])に合わせてサイトを調整したり、モデルやメーカー固有のパフォーマンスバグやリグレッションを特定します。

本ドキュメントは、User-Agent文字列からより積極的にエントロピーを除去し、本当にクライアントの詳細が必要なサーバーだけがそれらを受け取れるようにする仕組みを提案します。ブランドやバージョン情報、基盤となるOSのブランドとメジャーバージョン、デバイスの詳細を提供できる複数の新しいクライアントヒント([RFC8942])を導入します。これらのデータを常に全員に送信するのではなく、ユーザーエージェントはサイトごとの要求に応じてより細かいデータの送信可否を判断し、ネットワーク上に露出するパッシブフィンガープリンティングの表面を減らします(ベストプラクティス1[FINGERPRINTING-GUIDANCE]参照)。

1.1.

このセクションは規範的ではありません.

あるユーザーが最新バージョンの"Examplary Browser"でhttps://example.com/に初めてアクセスします。そのユーザーエージェントはHTTPリクエストとともに以下のヘッダーを送信します:

Sec-CH-UA: "Examplary Browser"; v="73", ";Not?A.Brand"; v="27"
Sec-CH-UA-Mobile: ?0
Sec-CH-UA-Platform: "Windows"

サーバーはユーザーの基盤プラットフォームバージョンに合わせたコンテンツをレンダリングしたいので、初回レスポンスでAccept-CHヘッダー([RFC8942]のSection 2.2.1)を送信して、追加情報を要求します:

Accept-CH: Sec-CH-UA-Platform-Version

これに応じて、ユーザーエージェントは次のリクエストでプラットフォームバージョン情報を含めます:

Sec-CH-UA: "Examplary Browser"; v="73", ";Not?A.Brand"; v="27"
Sec-CH-UA-Mobile: ?0
Sec-CH-UA-Platform: "Windows"
Sec-CH-UA-Platform-Version: "14.0.0"

1.2. ユースケース

このセクションは規範的ではありません.

このセクションでは、現在のUser-Agent文字列の用途と、UA-CH(User-Agent Client Hints)で同様の機能をどのように実現できるかを記載します。

1.2.1. 差別化配信

1.2.1.1. ブラウザ機能に基づく
このユースケースでは、polyfill.ioのようなサービスが、最新ブラウザユーザーの体験を損なうことなく、ユーザーごとにカスタムポリフィルを提供できます。

同様にJavaScriptを配信する際、最新のES機能が使えるブラウザにはトランスパイル(結果として肥大化や非効率なコードになる)を避けられます。画像配信時も、一部ブラウザはAcceptリクエストヘッダーを更新しない場合や、MIMEタイプだけでは同一フォーマットのバリアントを判別できない場合(例: WebP)もあり、その場合はブラウザとバージョンの情報が正しい画像バリアントの配信に不可欠です。

このユースケースを成立させるには、サーバーがブラウザとその意味のあるバージョンを把握し、それを利用可能な機能リストにマッピングする必要があります。これにより、どのポリフィルやコードバリアントを配信すべきかが分かります。

UA-CHでこれを行うサービスは、デフォルトで全リクエストに送信されるSec-CH-UAヘッダーを検査し、それに基づいてレスポンスを変更する必要があります。

1.2.1.2. ブラウザバグ回避策
一部のブラウザバージョンにはよく知られたバグがあり、コンテンツ側で回避策が必要です。そうしたバグを誘発すると、ブラウザのクラッシュやコンテンツ破損などの問題が発生し、これらは機能検出では判別できません。そのため、該当バージョンのブラウザに対してはコンテンツで回避策を講じる必要があります。

このユースケースでは、サーバーがブラウザとその意味あるバージョンを把握し、影響するバグを認識し、該当する場合に回避策を適用する必要があります。

UA-CHでこれを行うサービスは、デフォルトで全リクエストに送信されるSec-CH-UAヘッダーを検査し、それを使ってレスポンスを変更します。

1.2.2. マーケットシェア分析

ブラウザのマーケットシェアは非常に重要です。使用状況が見えることにより、開発者がそのブラウザでテストを行うよう促され、ユーザーの互換性問題を減らせます。さらに、マーケットシェアはブラウザベンダーのビジネス目標にも直接影響し、今後の開発が保証されます。

マーケットシェア分析には、サーバーが以下のいずれかの情報を認識する必要があります: ユーザーエージェント名とそのバージョン、OSとそのバージョン、デバイスモデル。それらを記録し、相対的なマーケットシェアを算出します。

UA-CHを使ってマーケットシェア分析を行いたいサイトは、デフォルトで全リクエストに送信されるSec-CH-UAヘッダーを検査して記録します。ユースケースによっては追加のUAクライアントヒント(例: モバイルデバイスモデル分析)も要求できます。

設計上、brandsリストの個々のエントリを見るだけでは、人気の低いブラウザの本当のブランド名と有名なブラウザのGREASE(偽ブランド)を区別しにくくなります。人気の低いブラウザは互換性目的で複数の有名ブランド名を含むことがあり、この手法だと、ユーザーは人気の高いブラウザの使用者として分類され、利用シェアの見方が歪むことになります。

そのため分析目的では、brandsリストをユニットとして扱い、区別したい(ブラウザ、バージョン)ペアごとに既知のbrandsリストと比較する方が良いです。新しいブラウザやバージョンが登場した際は既知リストを定期的に更新する必要がありますが、未知のブラウザで閉じること自体は問題になりません。

こうした既知brandsリストは中央で管理し、caniuseやMDNのように多くのサイトで利用されることもできます。

仕様では、ブラウザが送信するbrandsリストをバージョンごとに固定することを推奨しており、使用率集計を簡単にし、キャッシュにも有利です。既知brandsリストはブランドセットから(ブラウザ、バージョン)ペアへの単純なマッピングになります。

1.2.3. コンテンツ適応

コンテンツ適応とは、ユーザーのニーズに合わせて最適化されたコンテンツを提供することです。UA文字列以外にも様々な次元のコンテンツ適応があり、ビューポート寸法デバイスメモリユーザー設定などがあります。このサブセクションでは、現在のUser-Agent文字列に含まれる情報に依存するコンテンツ適応ニーズを扱います。
1.2.3.1. ブラウザベースの適応
一部サイトはブラウザごとに少し異なるコンテンツを提供します。理由は様々です。機能対応の違いによる体験差を正当化する場合もあれば、開発者がそのブラウザでテストしていない旨を警告するための場合もあります。中には、特定のブラウザユーザーを排除する目的もありますが、それは望ましくありません。

ブラウザとしては、前者は可能にし、後者は抑制したいと考えています。

1.2.3.2. モバイル専用サイト
多くのサイト運営者は、モバイルサイトとデスクトップサイトで異なるコンテンツを提供しています。レスポンシブWebデザインによって単一コードベースで複数フォームファクターに対応可能となりましたが、今でもモバイル専用バージョンがより適応的な場合もあります。

その場合、モバイルデバイスのユーザーにモバイル専用サイトを配信することが有効です。これを実現するには、HTML配信時にユーザーがモバイルデバイスかどうかをサーバーが把握する必要があります。

UA-CHでモバイル専用サイトを配信したいサイトは、デフォルトで全リクエストに送信されるSec-CH-UA-Mobileヘッダーを利用できます。

1.2.3.3. 低スペックデバイス
一部サイトは、CPU負荷の高い処理や大きな動画・画像を扱えない低スペックデバイスに異なるコンテンツを提供します。こうした適応は、現在のUser-Agent文字列に統合されたデバイスモデル情報を活用し、サーバー側データベースでモデルごとにメモリやCPU性能等のカテゴリに分類して実現します。

分岐基準がメモリであれば、Device-Memory Client Hintで判別可能です。その他の場合でもUA-CHでSec-CH-UA-Modelヒントを選択的に取得できます。

これらのヒントは初期状態では送信されないため、追加の設定が必要です。

トップレベルオリジンはAccept-CH: Device-Memory, Sec-CH-UA-Modelヘッダーをレスポンスに含めてヒントの送信を要求する必要があります。すべてのナビゲーションリクエストで適応が必須なら、ヒントがない場合はリダイレクトが必要です。あるいは、Critical-CHを使ってクライアント側に追加のリクエスト/レスポンス往復を処理させることもできます。

こうした適応を行う第三者オリジンは、トップレベルオリジンから委任が必要です。トップレベルオリジンはAccept-CHでヒントを要求し、さらにPermissions-Policyヘッダーで第三者オリジンへ委任する必要があります。

1.2.3.4. OS固有のスタイル
一部サイトはユーザーのOSに合わせてインターフェースを調整したい場合があります。プログレッシブエンハンスメント(例: スクリプトによるボタンスタイルの変更)が最善策ですが、プラットフォームやバージョンに基づいてインラインスタイルを提供したい場合もあります。

この場合は、前述の「低スペックデバイス」と同様に、Sec-CH-UA-PlatformおよびSec-CH-UA-Platform-Versionヒントを利用します。

1.2.3.5. OS統合
同様に、一部サイトはOS固有のリンク(例: Androidインテント リンク)への変更を行いたい場合があります。ここでも、スクリプトによるプログレッシブエンハンスメントでリンクを書き換えることができますが、サーバー側で適応したい場合があります。

この場合も「OS固有のスタイル」と同様に、Sec-CH-UA-PlatformSec-CH-UA-Platform-Versionヒントが必要です。

1.2.3.6. ブラウザ・OS固有の実験
サーバーによっては、特定のブラウザやプラットフォーム、バージョンのみに限定して多バリアント実験を行いたい場合があります。ブラウザとバージョン限定の実験は、リクエストごとにデフォルトで送信されるSec-CH-UA値を利用できます。プラットフォームとそのバージョンも必要なら、Sec-CH-UA-Platformはデフォルトで使えますが、Sec-CH-UA-Platform-Versionヒントは別途要求するか、クライアント側スクリプトで制御する必要があります。

1.2.4. ユーザーログイン通知

特にセキュリティ重視の多くのサイトでは、新しいデバイスからログインがあった際にユーザーへ通知を送ることがあります。これにより、ユーザーはログインを把握でき、もし本人または代理によるものでない場合に対応できます。

こうした通知を有効にするには、サイトはブラウザの商用ブランド名を認識し、ユーザーへ伝える必要があります。多くの場合、プラットフォーム名やバージョンも通知に含め、ユーザーがどのデバイスか判断できるようにします。

この種の通知はサーバー側適応を必要としないため、必要な情報取得にはuserAgentData.getHighEntropyValues()メソッドを使う方が適しています。

1.2.5. 適切なバイナリエグゼキュータブルのダウンロード

一部サイトはネイティブアプリケーションのバイナリエグゼキュータブルをダウンロードする用途があり、ユーザーに適切なバイナリをデフォルトで提案する必要があります。現在のユーザーに最適なバイナリは、OS、バージョン、ビット数、CPUアーキテクチャなど複数の要素で決まります。

このユースケースを解決するため、ダウンロードサイトはSec-CH-UA-PlatformSec-CH-UA-Platform-VersionSec-CH-UA-ArchSec-CH-UA-Bitnessヒント(またはAPIで取得)を利用して、ユーザーに最適なバイナリを提案できます。

1.2.6. コンバージョンモデリング

一部の機械学習モデルは、User-Agent文字列から様々な情報を取得して、ユーザー特性等を推定します。同様のモデリングは可能ですが、必要な情報収集には明示的なオプトインが必要となります。

1.2.7. 脆弱性フィルタリング

一部環境では、プロキシサーバーがユーザーのアクセス元デバイスが古くて脆弱でないかを検証する目的で使われます。Sec-CH-UAで得られるブラウザとバージョン情報も参考になりますが、ブラウザやOSのフルバージョンはこの種の分析では有用です。

こうしたプロキシは、リダイレクト手順を追加するか、Client Hint reliability mechanismsのいずれかを利用して、ブラウザのフルバージョンとプラットフォームバージョンの取得をオプトインし続ける必要があります。

1.2.8. ログとデバッグ

多くのサービスはUser-Agent文字列を記録し、過去のトラフィック解析やサービス関連のエラーのデバッグに活用しています。こうしたサービスは、Sec-CH-UAで得られる低エントロピー値を記録用に使うか、より高エントロピーなヒントの送信をオプトインする必要があります。後者はフォレンジック目的だけで行うべきではありませんが、特定の問題発生時にはより詳細なユーザーエージェント情報の取得(userAgentData.getHighEntropyValues() API利用)が有効な場合もあります。

1.2.9. フィンガープリンティング

ユーザーフィンガープリンティングとは、複数の情報源からユーザー情報を収集・組み合わせてユーザー固有の識別子を生成し、Cookieなどの状態を消しても後から認識できるようにする手法です。

この場合、オリジンはできるだけ多くのエントロピーを集めようとするため、あらゆるヒントを収集することになります。

1.2.9.1. スパムフィルタリングとボット検知
これはユーザーに敵対しないフィンガープリンティングのユースケースであり、維持したいものです。UA-CHでは、様々なヒントの能動的収集でこれが実現します。

将来的には、スパムフィルタリングやボット検知ユースケースを解決できる代替手法やAPIが登場することが期待されます。例えば、ブラウザがユーザーのために識別エントロピーの収集を制限する介入(Privacy Budget提案など)をする場合です。

1.2.9.2. 永続的なユーザー追跡
これは、本提案が明確に困難化しようとしているフィンガープリンティングのユースケースです。「スパムフィルタリング」と同様に、ユーザーについてあらゆるヒントを能動的に集めることは可能ですが、Privacy Budgetなどの提案はこれを防止し、永続的な追跡を可能にする代替手段は提供しません。
1.2.9.3. 既知のボット・クローラーのブロック
現状、User-Agent文字列は既知のボット・クローラーを強制的にブロックする手段として頻繁に使われています。通常トラフィックのエントロピー露出を減らすことで、ボットが人混みに紛れやすくなる懸念もありますが、だからといって大勢がより識別されやすくなるのは正当化できません。

スパムフィルタリングの場合と同様、将来的にはUser-Agent文字列照合に代わる手法が登場することが期待されます。

2. インフラストラクチャ

この仕様はClient Hints Infrastructure、HTTP Client Hints、Infra Standard、Permissions Policyに依存します。[CLIENT-HINTS-INFRASTRUCTURE] [RFC8942] [INFRA] [permissions-policy-1]

この仕様で使用される用語の一部は、Structured Field Values for HTTPで定義されています。[rfc9651]

3. ユーザーエージェントヒント

以下のセクションでは、サーバーが[RFC8942]で定義されたClient Hintsインフラストラクチャを通じて受信を選択できる、特定のユーザーエージェントに関する詳細を公開するHTTPリクエストヘッダーフィールドを定義します。以下の定義では、各ユーザーエージェントが自身のプロパティをいくつか定義していると仮定します:

ユーザーエージェント はこれらの文字列を簡潔に保つべきですが、サーバーはそれぞれの値を任意に受け入れなければなりません。これらはすべて ユーザーエージェント の気まぐれで構築されます。

ユーザーエージェント は高エントロピーな プラットフォームアーキテクチャ の値を以下のバケットにマッピングしなければなりません:

他の CPU アーキテクチャは、状況によってこれらの値のいずれかにマッピングするか、空文字列にマッピングしてもかまいません。

ユーザーエージェント は、どちらも次の条件が当てはまるプラットフォーム以外では プラットフォームアーキテクチャ または プラットフォームビット数 の値として空文字列または架空の値を返すべきです:

ユーザーエージェントmobileness が false の場合、model に対して空文字列を返さなければならない(MUST)。 また、ユーザーエージェントmobileness が true であっても、通常モデルが公開されるプラットフォームを除き、 model に空文字列を返さなければならない(MUST)。

ユーザーエージェントは、以下のいずれかのヒントがリクエストされた場合、プライバシー、互換性、その他の理由により、 型sf-stringのヒントでは空文字列、型sf-booleanのヒントではfalse、または他の架空の値を返してもよい(MAY): full versionplatform architectureplatform bitnesswow64-nessmodel

クライアントヒントプロパティ property が、指定された 環境設定オブジェクト environment settings のためにリクエストされた場合、次の手順を実行する:
  1. emulated client hints を、エミュレートされた UA クライアントヒントenvironment settings に関連付けられているものとする。

  2. emulated client hints が null でなく、かつ emulated client hintsproperty が未定義でない場合、 emulated client hintsproperty を返す。

  3. property の実装定義値を返す。

3.1. 「Sec-CH-UA」ヘッダーフィールド

Sec-CH-UA リクエストヘッダーフィールドは、サーバーへ ユーザーエージェントブランドおよび 重要なバージョン 情報を提供します。これは Structured Header であり、その値は リスト [rfc9651] でなければなりません。リストの項目はすべて string でなければなりません。それぞれの項目の値には ユーザーエージェント のバージョンを示す "v" パラメータを含めるべきです。

ヘッダーの ABNF は次の通りです:

Sec-CH-UA = sf-list

リクエストの Sec-CH-UA 値を返すために、次のステップを実行します:

  1. brands を "significant version" で create brands を実行した結果とする。

  2. listbrands と "significant version" で brand-version リストを作成する の結果とする。

  3. リストのシリアライズlist で実行した出力を返す。

注:ほとんどの Client Hints と異なり、 低エントロピーヒントテーブル に含まれるため、 Sec-CH-UA ヘッダーはサーバーが Accept-CH ヘッダーで受け取りを選択したかどうかに関係なくデフォルトで送信されます(ただし ポリシー制御クライアントヒント機能 により制御可能です)。これは ユーザーエージェント のブランド情報と重要なバージョン番号のみを含み(どちらも他のヘッダーの構造解析や、特定のブラウザリリース間で導入・変更された機能の利用可否をテストすればかなり明確に判別できる [Janc2014] ため)、低エントロピーとみなされます。

注: Sec-CH-UAブランドリスト内の各ブランドの主要バージョンを開示します。フルバージョン が必要なユースケースでは Sec-CH-UA-Full-Version-List を参照してください。

3.2. 'Sec-CH-UA-Arch' ヘッダーフィールド

Sec-CH-UA-Arch リクエストヘッダーフィールドは、特定のユーザーエージェントが実行されているプラットフォームのアーキテクチャに関する情報をサーバーに提供します。これは構造化ヘッダーであり、その値は文字列[rfc9651]でなければなりません。

ヘッダーのABNFは:

Sec-CH-UA-Arch = sf-string

3.3. 'Sec-CH-UA-Bitness' ヘッダーフィールド

Sec-CH-UA-Bitness リクエストヘッダーフィールドは、 サーバーに 指定されたプラットフォームのアーキテクチャのビット数に関する情報を提供します。ユーザーエージェントが 実行されているプラットフォームのアーキテクチャについての情報です。これは Structured Header であり、その値は文字列でなければなりません [rfc9651]

ヘッダーのABNFは以下の通りです:

Sec-CH-UA-Bitness = sf-string

3.4. 'Sec-CH-UA-Form-Factors' ヘッダーフィールド

Sec-CH-UA-Form-Factors リクエストヘッダーフィールドは、 サーバーに ユーザーエージェントフォームファクターに関する情報を提供します。これは Structured Header であり、その値はリストでなければなりません [rfc9651]。追加のフィンガープリント情報となるのを避けるため、 ヘッダーの値は辞書式順序で指定しなければならず、値は大文字・小文字を区別します。

このヘッダーは、デバイスのフォームファクターを、次の一般的なフォームファクター値のうち1つ以上を使用して記述すべきです: "Desktop"、"Automotive"、"Mobile"、 "Tablet"、"XR"、"EInk"、または "Watch"。該当するすべてのフォームファクター値を含めるべきです。

NOTE:

ユーザーエージェントのフォームファクターは、ユーザーがユーザーエージェントとどのようにやり取りするかを示します。許可されている値の意味は次の通りです:

ユーザーが意味のある異なる方法で対話する新しいフォームファクターがある場合、またはサイトがそのデバイスでユーザーとのやり取りを変更したい強いユースケースがあり、既存のヒントでその新しいフォームファクターを確実に判別できない場合は、新しい値を提案し、仕様に追加する必要があります。

ヘッダーのABNFは以下の通りです:

Sec-CH-UA-Form-Factors = sf-list

3.5. 'Sec-CH-UA-Full-Version' ヘッダーフィールド

Sec-CH-UA-Full-Version は非推奨であり、将来的に削除されます。開発者は代わりにSec-CH-UA-Full-Version-Listを使用してください。

Sec-CH-UA-Full-Version リクエストヘッダーフィールドは、サーバーにユーザーエージェントのフルバージョンに関する情報を提供します。これはStructured Headerであり、その値は文字列[rfc9651]でなければなりません。

ヘッダーのABNFは以下の通りです:

Sec-CH-UA-Full-Version = sf-string

3.6. 『Sec-CH-UA-Full-Version-List』ヘッダーフィールド

Sec-CH-UA-Full-Version-List リクエストヘッダーフィールドは、サーバーにそれぞれのブランドに対応したフルバージョンの情報を提供します。これはStructured Headerであり、その値はリスト[rfc9651]でなければなりません。

ヘッダーのABNFは以下の通りです:

Sec-CH-UA-Full-Version-List = sf-list

リクエストに対してSec-CH-UA-Full-Version-Listの値を返すには、次の手順を実行します:

  1. brands に "full version" を指定して create brands を実行した結果を代入します。

  2. listbrands と "full version" を用いて create a brand-version list を実行した結果を代入します。

  3. list を入力としてシリアライズした出力を返します。

3.7. 『Sec-CH-UA-Mobile』ヘッダーフィールド

Sec-CH-UA-Mobile リクエストヘッダーフィールドは、ユーザーエージェントが「モバイル」ユーザー体験を優先するかどうかに関する情報をサーバーに提供します。これはStructured Headerであり、その値はboolean[rfc9651]でなければなりません。

ヘッダーのABNFは以下の通りです:

Sec-CH-UA-Mobile = sf-boolean

Note: Sec-CH-UA と同様に、low entropy hint tableに含まれているため、 Sec-CH-UA-Mobile ヘッダーはサーバーが Accept-CH ヘッダーで受信を希望したかどうかに関わらずデフォルトで送信されます(ただし、policy-controlled client hints featureで制御可能です)。これは、ユーザーが直接制御可能な 1 ビットの情報であるため低エントロピーとみなされます。

3.8. 『Sec-CH-UA-Model』ヘッダーフィールド

Sec-CH-UA-Model リクエストヘッダーフィールドは、当該ユーザーエージェントが実行されているデバイスに関する情報をサーバーに提供します。これはStructured Headerであり、その値は文字列[rfc9651]でなければなりません。

ヘッダーのABNFは以下の通りです:

Sec-CH-UA-Model = sf-string

3.9. 『Sec-CH-UA-Platform』ヘッダーフィールド

Sec-CH-UA-Platform リクエストヘッダーフィールドは、当該ユーザーエージェントが実行されているプラットフォームに関する情報をサーバーに提供します。これはStructured Headerであり、その値は文字列[rfc9651]でなければなりません。その値は一般的なプラットフォーム値("Android", "Chrome OS", "Fuchsia", "iOS", "Linux", "macOS", "Windows", "Unknown")のいずれかに一致することが推奨されます。

ヘッダーのABNFは以下の通りです:

Sec-CH-UA-Platform = sf-string

Note: Sec-CH-UA 同様、low entropy hint tableに含まれているため、Sec-CH-UA-Platform ヘッダーはサーバーが Accept-CH ヘッダーで受信を希望したかどうかに関わらずデフォルトで送信されます(ただし、policy-controlled client hints featureで制御可能です)。

3.10. 『Sec-CH-UA-Platform-Version』ヘッダーフィールド

Sec-CH-UA-Platform-Version リクエスト ヘッダーフィールドは、サーバーに対して、指定された プラットフォームバージョン 上で実行されている ユーザーエージェント についての情報を提供する。 これは 構造化ヘッダー であり、その値は 文字列 [rfc9651] でなければならない (MUST)。 その値は プラットフォームブランドプラットフォームバージョンを取得する 結果となる。

文字列 platform が与えられたときに プラットフォームバージョンを取得するには、次の手順を実行する:

  1. platform が "Linux" または "Fuchsia" の場合:

    1. 空文字列を返す。

  2. platform が "Android" の場合:

    1. platformReturnedVersionString に OS の android.os.Build.VERSION.RELEASE 文字列から取得した結果をセットする。

    2. create a unified platform version stringplatformReturnedVersionStringを引数にして実行した結果を返す。

  3. platform が "iOS" の場合:

    1. platformReturnedVersionStringUIDevice オブジェクトの systemVersion を取得した結果をセットする。

    2. create a unified platform version stringplatformReturnedVersionString を引数にして実行した結果を返す。

  4. platform が "Windows" の場合:

    1. 利用可能な場合(つまり、Windows 10 以上)、platformReturnedVersionStringWindows.Foundation.UniversalApiContract の整数バージョンを取得し、文字列に変換した結果を代入する。それ以外の場合は、platformReturnedVersionStringレガシー Windows バージョン番号の取得の結果を代入する。

    2. create a unified platform version stringplatformReturnedVersionString を引数にして実行した結果を返す。

  5. platformVersionComponentListリストとして用意する。

  6. platform が "macOS" の場合:

    1. macOSVersionNSProcessInfo オブジェクトの operatingSystemVersion プロパティを取得して代入する。

    2. AppendmacOSVersionmajorVersionminorVersionpatchVersion を(この順で)platformVersionComponentListに追加する。

  7. platform がその他の場合:

    1. Append で、他ブラウザーとの互換性保持に最も適する形式の 1~3 個のバージョンパーツを platformVersionComponentList に追加する。

    2. platformVersionComponentList の長さが3未満の間、append で "0" を追加する。

  8. concatenation を用いて、platformVersionComponentListを U+002E FULL STOP (.) 区切りで結合したものを返す。

get the legacy Windows version numberは、次の手順を実行します:

  1. OSVERSIONINFOdwMajorVersionmajor に代入します。

  2. OSVERSIONINFOdwMinorVersionminor に代入します。

  3. major6 かつ minor3 (すなわち Windows 8.1)の場合、"0.3" を返します。

  4. major6 かつ minor2 (すなわち Windows 8)の場合、"0.2" を返します。

  5. major6 かつ minor1 (すなわち Windows 7)の場合、"0.1" を返します。

  6. それ以外の場合は "0" を返します。

create a unified platform version stringは、文字列inputが与えられたとき、以下の手順を実行します:

  1. platformVersionComponentListリストとし、index を 0 に初期化します。

  2. platformVersionUnprocessedTokenListstrictly splittinginput を U+002E FULL STOP (.) で分割したリストとします。

  3. index が 3 未満の間、次を繰り返します:

    1. indexplatformVersionUnprocessedTokenList の長さ未満の場合:

      1. platformVersionUnprocessedTokenList[index] が符号なし整数ならば文字列に変換してappendplatformVersionComponentListに追加。

      2. それ以外の場合はappendで"0"を追加。

    2. そうでなく indexplatformVersionUnprocessedTokenList の長さ以上の場合:

      1. Appendで"0"を追加。

    3. index を1つ増やす。

  4. concatenation を用いて platformVersionComponentList を U+002E FULL STOP (.) 区切りで結合した値を返す。

ヘッダーのABNFは以下の通りです:

Sec-CH-UA-Platform-Version = sf-string

3.11. 『Sec-CH-UA-WoW64』ヘッダーフィールド

Sec-CH-UA-WoW64 リクエストヘッダーフィールドは、 サーバーに 64ビットWindows上でユーザーエージェントバイナリが32ビットモードで動作しているかどうかに関する情報を提供します。 これはStructured Headerであり、その値はboolean [rfc9651] でなければなりません。

ヘッダーのABNFは次のとおりです:

Sec-CH-UA-WoW64 = sf-boolean

Note: これらのクライアントヒントは以下のclient hints tokensセットで呼び出すことができます: Sec-CH-UA, Sec-CH-UA-Arch, Sec-CH-UA-Bitness, Sec-CH-UA-Form-Factors, Sec-CH-UA-Full-Version, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA-WoW64

4. インターフェイス

dictionary NavigatorUABrandVersion {
  DOMString brand;
  DOMString version;
};

dictionary UADataValues {
  DOMString architecture;
  DOMString bitness;
  sequence<NavigatorUABrandVersion> brands;
  sequence<DOMString> formFactors;
  sequence<NavigatorUABrandVersion> fullVersionList;
  DOMString model;
  boolean mobile;
  DOMString platform;
  DOMString platformVersion;
  DOMString uaFullVersion; // deprecated in favor of fullVersionList
  boolean wow64;
};

dictionary UALowEntropyJSON {
  sequence<NavigatorUABrandVersion> brands;
  boolean mobile;
  DOMString platform;
};

[Exposed=(Window,Worker)]
interface NavigatorUAData {
  readonly attribute FrozenArray<NavigatorUABrandVersion> brands;
  readonly attribute boolean mobile;
  readonly attribute DOMString platform;
  Promise<UADataValues> getHighEntropyValues(sequence<DOMString> hints);
  UALowEntropyJSON toJSON();
};

interface mixin NavigatorUA {
  [SecureContext] readonly attribute NavigatorUAData userAgentData;
};

Navigator includes NavigatorUA;
WorkerNavigator includes NavigatorUA;

Note: ユーザーエージェント情報の高エントロピー部分は、 Promise を通じて取得されます。 これはユーザーエージェントが、 (たとえばユーザーの許可を求めるなど)時間のかかる確認の背後でそれらの公開を制御できるようにするためです。

4.1. 処理モデル

4.1.1. WindowOrWorkerGlobalScope

ユーザーエージェントには、関連付けられたbrandsがあり、これは create brandssignificant versionで実行することで生成される リストです。

すべてのWindowOrWorkerGlobalScope オブジェクトには、 関連付けられた brands frozen arrayがある。 これは FrozenArray<NavigatorUABrandVersion> であり、 frozen arrayの作成ユーザーエージェントbrands から生成される。

また、すべてのWindowOrWorkerGlobalScope オブジェクトには 関連付けられた full version list frozen arrayがある。 これは FrozenArray<NavigatorUABrandVersion> であり、 frozen arrayの作成create brandsfull version で実行した結果に対して生成されたものです。

4.1.2. brands の作成

create brandsversion typeを指定して呼び出す場合は、次の手順を実行します:

  1. listリストとします。

  2. Assert version typeが"full version"または"significant version"のいずれかであること。

  3. brandごとに(それがユーザーエージェント等価クラスを表す場合)、 brandについて:

    1. versionstringとして初期化し、次に従う:

      1. もしversion typeが"full version"なら、versionfull version  に対応する文字列とする。

      2. もしversion typeが"significant version"なら、versionsignificant version に対応する文字列とする。

    2. dictを新しいNavigatorUABrandVersion辞書として生成し、 brandbrandを、 versionversionを設定。

    3. Appenddictlistへ追加。

  4. ユーザーエージェントは次を実施すべき:

    1. Appendでもう1件 itemlistへ追加し、内容は NavigatorUABrandVersion 辞書(brandarbitrary brandを、 versioncreate an arbitrary version(引数は version type)の結果)とする。

    2. itemの順序をランダム化。

    補足: これらのランダム成分を生成する際にキャッシュのばらつきを最小限に抑える1つの方法として、ビルド時に決定し、ユーザーエージェント の重要なバージョンの存続期間中は同一のままにしておくことが考えられる。

    補足: これらのランダム化手順がいつ・なぜ適切となるかの詳細については、§ 8.2 GREASE風 UAブランドリスト を参照のこと。

  5. listを返す。

equivalence classは互換性があるとみなされるブラウザーのグループを表します。たとえば共通のレンダリングエンジンを用いる場合、その equivalence class となります。

4.1.3. 任意ブランドとバージョン値の生成

arbitrary brand の作成のために、ユーザーエージェントは次を実行しなければなりません:

  1. arbitraryBrandASCIIアルファベットと0x20(SP)だけからなる文字列とし、0x20(SP)を1つ以上含み、かつ全長20ASCIIバイト以下、先頭末尾に0x20(SP)不可。

  2. arbitraryBrandListASCIIホワイトスペースで分割した配列を格納。

  3. greaseyStackstackとして用意。

  4. greaseyCharsASCII bytes « 0x20 (SP), 0x28 (, 0x29 ), 0x2D -, 0x2E ., 0x2F /, 0x3A :, 0x3B ;, 0x3D =, 0x3F ?, 0x5F _ » のリストとする。

  5. indexを0で初期化。

  6. indexarbitraryBrandListサイズ−1未満の間:

    1. PushgreaseyCharsからランダムに選んだitemgreaseyStackに積む。

    2. indexを1増やす。

  7. greaseyBrandListリストとしindex=0にする。

  8. greaseyStack空でない間:

    1. AppendarbitraryBrandList[index]をgreaseyBrandListに追加。

    2. itempoppingした値を格納。

    3. AppenditemgreaseyBrandListに追加。

    4. indexを1増やす。

  9. AppendarbitraryBrandList[index]をgreaseyBrandListに追加。

  10. 先頭・末尾の ASCII ホワイトスペースを除去し、その上で文字列連結(区切りなし)したgreaseyBrandListの結果を返す。

このアルゴリズムの結果、先頭末尾にgreaseyCharsが付与されない任意ブランドが生成されます。実装経験上、これらはWeb互換性がないことが示されています。

また、Structured Headersは0x22(\")や0x5C(\\)のエスケープも許しますが、これらはファイアウォールとの互換性問題も引き起こします。

arbitrary version の作成は、version typeを引数に次の手順を実施:

  1. Assert version typeが"full version"または"significant version"どちらかであること。

  2. arbitrary versionstringで初期化し次に従う:

    1. もしversion typeが"full version"なら、arbitrary versionfull version の形式に一致する文字列とし、値自体は一致させない。

    2. もしversion typeが"significant version"なら、arbitrary versionsignificant version の形式に一致するが値は異なるものとする。

  3. arbitrary versionを返す。

Note: ユーザーエージェントは必要に応じ、バージョンチェックが正しく行われるよう任意に低いバージョンを送信することができ、また適宜値を変化させるべきです。

4.1.4. ブランド-バージョンリスト作成

ブランド-バージョンリスト作成brandsversion typeを与えて、次の手順を実行します:

  1. listリストとして初期化(空)。

  2. Assert version typeは"full version"または"significant version"のいずれかであること。

  3. brands内の各brandについて:

    1. versionを文字列として、次の通り初期化:

      1. version typeが"full version"なら、versionフルバージョンに対応する文字列。

      2. version typeが"significant version"なら、version重要バージョンに対応する文字列。

    2. parameter辞書として初期化(空)。

    3. parameter["param_key"]に "v" をセット。

    4. parameter["param_value"]にversionをセット。

    5. pairbrandbrandparameterのタプルとする。

    6. listへ pairを追加。

  4. listを返す。

4.1.5. ゲッター

取得時、brands 属性はthis関連グローバルオブジェクトbrands frozen arrayを返さなければなりません。

取得時、mobile 属性はユーザーエージェントmobilenessを返さなければなりません。

取得時、platform 属性はユーザーエージェントplatform brandを返さなければなりません。

4.1.6. getHighEntropyValues メソッド

getHighEntropyValues(hints) メソッドは以下の手順を実行しなければなりません:

  1. p新しい promiseとして現在のレルムで作成します。

  2. uaDataを新しいUADataValuesとして生成します。

  3. uaData["brands"]にthis関連グローバルオブジェクトbrands frozen array を設定します。

  4. uaData["mobile"]に ユーザーエージェントmobilenessを設定します。

  5. uaData["platform"]に ユーザーエージェントplatform brandを設定します。

  6. もしthis関連グローバルオブジェクト関連付けられた Documentch-ua-high-entropy-values機能の 使用を許可されていない場合、puaDataで解決します。

  7. そうでない場合、次の手順を並列で実行します:

    1. もしhints"architecture"を含むなら、uaData["architecture"]に ユーザーエージェントplatform architectureを設定します。

    2. もしhints"bitness"を含むなら、uaData["bitness"]に ユーザーエージェントplatform bitnessを設定します。

    3. もしhints"formFactors"を含むなら、uaData["formFactors"]に ユーザーエージェントform-factorsを設定します。

    4. もしhints"fullVersionList"を含むなら、uaData["fullVersionList"]に this関連グローバルオブジェクトfull version list frozen arrayを設定します。

    5. もしhints"model"を含むなら、uaData["model"] に ユーザーエージェントmodelを設定します。

    6. もしhints"platformVersion"を含むなら、uaData["platformVersion"] にplatform versionの取得platform brandで)結果を設定します。

    7. もしhints"uaFullVersion"を含むなら、uaData["uaFullVersion"]

    8. もしhints"wow64"を含むなら、uaData["wow64"] にユーザーエージェントのwow64-nessを設定します。

    9. permission task sourceタスクキューresolve p with uaDataのタスクを入れる。

  8. pを返します。

4.1.7. toJSON メソッド

toJSON() メソッドは次の手順を実行しなければなりません:

  1. uaLowEntropyDataを新しいUALowEntropyJSON とする

  2. uaLowEntropyData["brands"] にthis関連グローバルオブジェクトbrands frozen arrayを設定します。

  3. uaLowEntropyData["mobile"] にユーザーエージェントmobilenessを設定します。

  4. uaLowEntropyData["platform"] にユーザーエージェントplatform brandを設定します。

  5. uaLowEntropyDataを返します

5. オートメーション

ユーザーエージェントの自動化およびアプリケーションテストの目的のために、本書は [WebDriver-BiDi] 仕様への拡張を定義する。

5.1. 定義

UserAgentClientHintsCommand = (
  userAgentClientHints.SetClientHintsOverrideCommand
)

A ブランドバージョンとは、以下を持つ構造体です:

ユーザーエージェントクライアントヒントとは、以下を持つ構造体です:

remote end には関連付けられた emulated client hints がある。これは struct であり、次のものを持つ:

5.2. userAgentClientHints.setClientHintsOverride コマンド

userAgentClientHints.setClientHintsOverride コマンドは、 navigable または ユーザーコンテキスト のリストや、グローバルに対して、 エミュレートされたユーザーエージェントクライアントヒントを設定または削除する。

コマンドタイプ
userAgentClientHints.SetClientHintsOverrideCommand = {
    method: "userAgentClientHints.setClientHintsOverride",
    params: {
        clientHints: userAgentClientHints.ClientHintsMetadata / null,
        ? contexts: [+text],
        ? userContexts: [+text],
    }
}

userAgentClientHints.ClientHintsMetadata = {
    ? brands: [* userAgentClientHints.BrandVersion],
    ? fullVersionList: [* userAgentClientHints.BrandVersion],
    ? platform: text,
    ? platformVersion: text,
    ? architecture: text,
    ? model: text,
    ? mobile: bool,
    ? bitness: text,
    ? wow64: bool,
    ? formFactors: [* text];
}

userAgentClientHints.BrandVersion = {
    brand: text,
    version: text
}
戻り値の型
userAgentClientHints.SetClientHintsOverrideResult = {}
エミュレートされたUAクライアントヒントは、環境設定オブジェクト environment settings に関連付けられたものであり、次の手順の結果である:
  1. related navigables関連する navigable の取得environment settings での結果とする。

  2. related navigables のそれぞれの navigable について:

    1. top-level navigablenavigableトップレベルトラバーサブルとする。

    2. user contexttop-level navigable関連付けられたユーザーコンテキストとする。

    3. もし emulated client hintsnavigableごとの emulated client hintstop-level navigable を含むならば、emulated client hintsnavigableごとの emulated client hints[top-level navigable] を返す。

    4. もし emulated client hintsユーザーコンテキストごとの emulated client hintsuser context を含むならば、emulated client hintsユーザーコンテキストごとの emulated client hints[user context] を返す。

  3. default emulated client hintsemulated client hintsデフォルトの emulated client hints とする。

  4. もし default emulated client hints が null でなければ、 default emulated client hints を返す。

  5. null を返す。

remote end の手順command parameters与えられた場合)は次の通り:

  1. もし command parameters"userContexts" を含み かつ command parameters"contexts" を含む場合、 errorerror code invalid argument で返す。

  2. emulated client hintscommand parameters["clientHints"] とする。

  3. もし command parameters"contexts" を含むなら:

  4. navigablestry での ID指定で有効なトップレベルトラバーサブルの取得command parameters["contexts"] を適用した結果とする。

  5. navigable について:

    1. もし emulated client hints が null なら navigable を emulated client hintsnavigable ごとの emulated client hints から削除する。

    2. そうでなければ、setemulated client hintsnavigable ごとの emulated client hints[navigable] に emulated client hints をセットする。

  6. success を data null で返す。

  7. もし command parameters"userContexts" を含むなら:

  8. user contextstry の 有効なユーザーコンテキスト取得command parameters["userContexts"] での結果とする。

  9. user context について:

    1. もし emulated client hints が null なら user context を emulated client hintsユーザーコンテキストごとの emulated client hints から削除する。

    2. そうでなければ、setemulated client hintsユーザーコンテキストごとの emulated client hints[user context] に emulated client hints をセットする。

  10. success を data null で返す。

  11. セットemulated client hintsデフォルトの emulated client hintsemulated client hints を設定する。

  12. success を data null で返す。

6. Permissions-Policy 統合

この仕様は、"ch-ua-high-entropy-values"という文字列で識別されるポリシー制御機能を定義しており、デフォルト許可リスト'*'です。これにより、ドキュメントが高エントロピークライアントヒントの値を getHighEntropyValues() API経由で返せるかを決定します。

Note: ドキュメントが"ch-ua-high-entropy-values"機能を 使用できない場合でも、getHighEntropyValues() APIは利便性のために低エントロピー値を返し続けます。

7. セキュリティおよびプライバシーに関する考慮事項

7.1. セキュアトランスポート

クライアントヒントは非セキュアなエンドポイントには配信されません([RFC8942]第2.2.1節のセキュアトランスポート要件を参照)。これはユーザーエージェント情報が平文チャネル経由で漏えいしないことを意味し、ネットワーク攻撃者が特定エージェントの行動を時間をかけてプロファイリングする機会を減らします。

7.2. 委譲

クライアントヒントはPermissions Policy ([permissions-policy-1])を通じてトップレベルページから委譲されます。これにより、ユーザーエージェント情報が サブリソースリクエストと共に配信される可能性、つまりパッシブフィンガープリンティングの可能性が低下します。

この委譲は、リクエストへのクライアントヒント追加の一部として定義されています。

7.3. フィンガープリンティング

User Agent Client Hints の 主な目的 は、User-Agent ヘッダーフィールドを通じてウェブ全体に対してデフォルトで公開されるエントロピーの量を削減することにあり、これは パッシブフィンガープリンティング の目的に利用され得る。

ユーザーエージェントは、どのヒントを提供するかを決定でき、期待されるのは、無編集(unredacted)の User-Agent ヘッダーフィールドに含まれる以上の情報は提供しないことである。 ユーザーエージェントは、提供したくない値については空文字列を返すか、あるいはヒント自体をまったく返さないこともできる。

しかし、やはり一部またはすべてのヒントは、一次あるいは委譲された第三者によって アクティブフィンガープリンティング の目的でリクエスト・利用される可能性がある。 § 7.4 アクセス制限 で述べたように、 ユーザーエージェントは、自分のユーザーを 積極的にフィンガープリンティング していると知られている主体へのアクセスを制限・抑制する方針を検討すべきである。

ユーザーエージェントは、個人やごく少数のユーザーに対してユニークとなる恐れのある GREASE 風ブランドリストを通じてフィンガープリンティングのベクトルを導入しないよう注意すべきである。 むしろ、恣意的なブランドは多くのユーザー間(例:すべてのユーザーでメジャーバージョン間で安定して共有)で共有される戦略を取るべきである。

7.4. アクセス制限

上記で定義されたクライアントヒントの情報は、ユーザーエージェントとそのデバイスについて多くの情報を明らかにします。 ユーザーエージェントは、 この情報へのアクセス許可時に慎重な判断を下す必要があり、 上記のセキュアトランスポートや委譲要件に加え、さらなる制限を課すこともできます。例として、ユーザーエージェントプラットフォームアーキテクチャプラットフォームビット数を ダウンロードするつもりがあるリクエストでのみ公開し、 サーバーが適切なバイナリを提供できるようにすることも可能です。同様に、ユーザーに公開値を制御させたり、 明示的なユーザー操作(パーミッションプロンプトや設定画面など)を経てアクセスさせたりすることもできます。

8. 実装上の考慮点

8.1. 'User-Agent' ヘッダー

ユーザーエージェントは、User-Agentヘッダーの利用をこの文書で説明されているクライアントヒントモデルを優先して、その情報粒度を下げることで非推奨化すべきです。このヘッダーは近いうちに完全削除することは困難で、既存サイトのコンテンツネゴシエーションコードが存在を前提にし続けるからです([Rossi2015]の新しいブラウザが直面した課題が最近例)。

推奨されるアプローチのひとつは、各ユーザーエージェントUser-Agentヘッダー値をロックし、 "like Gecko"や"AppleWebKit/537.36"といった記述を永続的に保つことで後方互換性を維持することです。この向きを徐々に強化し、まずバージョン番号の固定、その後プラットフォーム・モデル情報をより一般的なものに置き換えることでヘッダーのフィンガープリント性を低減できます。

8.2. GREASE風UAブランドリスト

過去から、ユーザーエージェントがブランドを偽り、サイトのスニフィングスクリプトをすり抜けたり、UAベースの許可・ブロックリストでユーザーがブロックされるのを防ぐインセンティブがあることが分かっています。

短期的にはbrandsリストの乱用防止に期待値リセットが役立つかもしれませんが、長期的にはおそらく効果がありません。ネットワークプロトコル分野ではGREASEという概念があります([I-D.ietf-tls-grease])。 この問題に対しその概念を引用できます。

ユーザーエージェントbrandsに複数エントリが含まれることで、 brandsリストの標準的な処理を促すことができます。 ランダムかつ恣意的順序で、追加かつ意図的に間違えたカンマ区切り値を含めれば、特定値だけに依存する事態を減らせます。

いくつかの例を見てみましょう:

ユーザーエージェントbrandsに任意の値を含む2つ以上のエントリを必ず含めなければなりません。

brandsの値の順序も、特定値が特定の位置にあることに依存できないようにし、時間とともに変化しなければなりません。

GREASE戦略選択時、ユーザーエージェントはキャッシュ分散や分析用途を考慮し、同じユーザーエージェントバージョン間での分散を最小化すべきです。

補足: キャッシュや解析のばらつきを最小限に抑える一つの方法として、UAセットのGREASE部分をビルド時に決定し、ユーザーエージェントの重要なバージョンの存続期間中はそれらを同一のままにしておくことが挙げられる。

8.3. 'Sec-CH-' プレフィックス

UA-CHヘッダーに対してユーザーランドJavaScriptの影響や改変を制限することには、セキュリティ面で様々な利点があります。同時に、そのようなユーザーランドの書き換えが必要となる正当なユースケースも存在しないようです。

そのためTAGとの議論をもとに、JavaScript(例:fetchやService Worker経由)から これらヘッダーへの書き込みアクセスは禁止し、ブラウザー制御クライアントヒントとして区別、 リクエストに含めれてもCORSプリフライトを発生させないよう記録・文書化しています。

したがって、この仕様で定義されているリクエストヘッダーにはSec-CH-プレフィックスが含まれます。

9. IANA に関する考慮事項

本ドキュメントは、Sec-CH-UASec-CH-UA-ArchSec-CH-UA-BitnessSec-CH-UA-Form-FactorsSec-CH-UA-Full-VersionSec-CH-UA-MobileSec-CH-UA-ModelSec-CH-UA-PlatformSec-CH-UA-Platform-VersionSec-CH-UA-WoW64Sec-CH-UA-Full-Version-List HTTPリクエストヘッダーフィールドを定義し、恒久的なメッセージヘッダーフィールドレジストリ([RFC3864])に登録することを意図します。

また、User-Agentヘッダーフィールドの使用を非推奨化することも意図しています。

9.1. 'Sec-CH-UA' ヘッダーフィールド

ヘッダーフィールド名: Sec-CH-UA

適用プロトコル: http

状態: 標準

著者/変更管理: IETF

仕様ドキュメント: 本仕様(§ 3.1 The 'Sec-CH-UA' Header Field

9.2. 'Sec-CH-UA-Arch' ヘッダーフィールド

ヘッダーフィールド名: Sec-CH-UA-Arch

適用プロトコル: http

状態: 標準

著者/変更管理: IETF

仕様ドキュメント: 本仕様(§ 3.2 The 'Sec-CH-UA-Arch' Header Field

9.3. 'Sec-CH-UA-Bitness' ヘッダーフィールド

ヘッダーフィールド名: Sec-CH-UA-Bitness

適用プロトコル: http

状態: 標準

著者/変更管理: IETF

仕様ドキュメント: 本仕様(§ 3.3 The 'Sec-CH-UA-Bitness' Header Field

9.4. 'Sec-CH-UA-Form-Factors' ヘッダーフィールド

ヘッダーフィールド名: Sec-CH-UA-Form-Factors

適用プロトコル: http

状態: 標準

著者/変更管理: IETF

仕様ドキュメント: 本仕様(§ 3.4 The 'Sec-CH-UA-Form-Factors' Header Field

9.5. 'Sec-CH-UA-Full-Version' ヘッダーフィールド

ヘッダーフィールド名: Sec-CH-UA-Full-Version

適用プロトコル: http

状態: 非推奨

著者/変更管理: IETF

仕様ドキュメント: 本仕様(§ 3.5 The 'Sec-CH-UA-Full-Version' Header Field

9.6. 'Sec-CH-UA-Full-Version-List' ヘッダーフィールド

ヘッダーフィールド名: Sec-CH-UA-Full-Version-List

適用プロトコル: http

状態: 標準

著者/変更管理: IETF

仕様ドキュメント: 本仕様(§ 3.6 'Sec-CH-UA-Full-Version-List' ヘッダーフィールド

9.7. 'Sec-CH-UA-Mobile' ヘッダーフィールド

ヘッダーフィールド名: Sec-CH-UA-Mobile

適用プロトコル: http

状態: 標準

著者/変更管理: IETF

仕様ドキュメント: 本仕様(§ 3.7 The 'Sec-CH-UA-Mobile' Header Field

9.8. 'Sec-CH-UA-Model' ヘッダーフィールド

ヘッダーフィールド名: Sec-CH-UA-Model

適用プロトコル: http

状態: 標準

著者/変更管理: IETF

仕様ドキュメント: 本仕様(§ 3.8 The 'Sec-CH-UA-Model' Header Field

9.9. 'Sec-CH-UA-Platform' ヘッダーフィールド

ヘッダーフィールド名: Sec-CH-UA-Platform

適用プロトコル: http

状態: 標準

著者/変更管理: IETF

仕様ドキュメント: 本仕様(§ 3.9 The 'Sec-CH-UA-Platform' Header Field

9.10. 'Sec-CH-UA-Platform-Version' ヘッダーフィールド

ヘッダーフィールド名: Sec-CH-UA-Platform-Version

適用プロトコル: http

状態: 標準

著者/変更管理: IETF

仕様ドキュメント: 本仕様(§ 3.10 The 'Sec-CH-UA-Platform-Version' Header Field

9.11. 'Sec-CH-UA-WoW64' ヘッダーフィールド

ヘッダーフィールド名: Sec-CH-UA-WoW64

適用プロトコル: http

状態: 標準

著者/変更管理: IETF

仕様ドキュメント: 本仕様(§ 3.11 The 'Sec-CH-UA-WoW64' Header Field

9.12. 'User-Agent' ヘッダーフィールド

ヘッダーフィールド名: User-Agent

適用プロトコル: http

状態: 非推奨

著者/変更管理: IETF

仕様ドキュメント: 本仕様(§ 8.1 The 'User-Agent' Header)、および [rfc9110]の5.5.3節

10. 謝辞

次の方々に、この仕様への貴重なフィードバックと貢献を感謝します: Aaron Tagliaboschi, Ali Beyad, ArkUmbra, Dustin Mitchell, Erik Anderson, jasonwee, Luke Williams, Mike West, Martin Thomson, そして Toru Kobayashi

適合性

文書規約

適合要件は説明的な断言と RFC 2119 の用語の組み合わせで記述されています。 この文書の規範部分における「MUST」「MUST NOT」「REQUIRED」「SHALL」「SHALL NOT」「SHOULD」「SHOULD NOT」「RECOMMENDED」「MAY」「OPTIONAL」というキーワードは RFC 2119 で示される意味に従って解釈されます。 ただし、可読性のため、これらの語は仕様内ですべて大文字では記載されていません。

この仕様のすべての文は、 明示的に非規範とされた節、例、および注記を除き、規範的です。[RFC2119]

この仕様の例は、"for example" という語で始めるか、規範テキストと区別して class="example" を付与して示します。 例:

これは情報例の一例です。

情報注記は "Note" で始まり、規範テキストと区別して class="note" を付与して示します。 例:

注: これは情報注記の例です。

索引

本仕様で定義された用語

他で定義された用語

参考文献

規範的参考文献

[CLIENT-HINTS-INFRASTRUCTURE]
クライアントヒントインフラストラクチャ.ドラフトコミュニティグループレポート.URL: https://wicg.github.io/client-hints-infrastructure/
[COMPAT]
Mike Taylor.互換性標準.リビングスタンダード.URL: https://compat.spec.whatwg.org/
[HTML]
Anne van Kesteren 他.HTML標準.リビングスタンダード.URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren;Domenic Denicola.インフラ標準.リビングスタンダード.URL: https://infra.spec.whatwg.org/
[PERMISSIONS-POLICY-1]
Ian Clelland.パーミッションポリシー.URL: https://w3c.github.io/webappsec-permissions-policy/
[RFC2119]
S. Bradner.RFCで要求レベルを示すキーワード.1997年3月.ベストプラクティス.URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC8610]
H. Birkholz;C. Vigano;C. Bormann.簡潔なデータ定義言語(CDDL):簡潔なバイナリオブジェクト表現(CBOR)およびJSONデータ構造を記述するための表記規則.2019年6月.提案標準.URL: https://www.rfc-editor.org/rfc/rfc8610
[RFC8942]
I. Grigorik;Y. Weiss.HTTPクライアントヒント.2021年2月.実験的.URL: https://www.rfc-editor.org/rfc/rfc8942
[RFC9651]
M. Nottingham;P-H. Kamp.HTTPの構造化フィールド値.2024年9月.提案標準.URL: https://www.rfc-editor.org/rfc/rfc9651
[WebDriver-BiDi]
James Graham;Alex Rudenko;Maksim Sadym.WebDriver BiDi.URL: https://w3c.github.io/webdriver-bidi/
[WEBDRIVER1]
Simon Stewart; David Burns. WebDriver(ウェブドライバー)。URL: https://w3c.github.io/webdriver/
[WEBDRIVER2]
Simon Stewart;David Burns.WebDriver.URL: https://w3c.github.io/webdriver/
[WEBIDL]
Edgar Chen;Timothy Gu.Web IDL標準.リビングスタンダード.URL: https://webidl.spec.whatwg.org/

参考情報

[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. URL: https://drafts.csswg.org/css-values-4/
[FacebookYearClass]
Chris Marra; Daniel Weaver. Year class: A classification system for Android. URL: https://engineering.fb.com/android/year-class-a-classification-system-for-android/
[FINGERPRINTING-GUIDANCE]
Nick Doty; Tom Ritter. Mitigating Browser Fingerprinting in Web Specifications. URL: https://w3c.github.io/fingerprinting-guidance/
[I-D.ietf-tls-grease]
David Benjamin. Applying GREASE to TLS Extensibility. ID. URL: https://tools.ietf.org/html/draft-ietf-tls-grease
[Janc2014]
Artur Janc; Michal Zalweski. Technical analysis of client identification mechanisms. URL: https://dev.chromium.org/Home/chromium-security/client-identification-mechanisms#TOC-Browser-level-fingerprints
[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
[RFC9110]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. HTTP Semantics. June 2022. Internet Standard. URL: https://httpwg.org/specs/rfc9110.html
[Rossi2015]
The Microsoft Edge Rendering Engine that makes the Web just work. URL: https://channel9.msdn.com/Events/WebPlatformSummit/2015/The-Microsoft-Edge-Rendering-Engine-that-makes-the-Web-just-work#time=9m45s

IDL索引

dictionary NavigatorUABrandVersion {
  DOMString brand;
  DOMString version;
};

dictionary UADataValues {
  DOMString architecture;
  DOMString bitness;
  sequence<NavigatorUABrandVersion> brands;
  sequence<DOMString> formFactors;
  sequence<NavigatorUABrandVersion> fullVersionList;
  DOMString model;
  boolean mobile;
  DOMString platform;
  DOMString platformVersion;
  DOMString uaFullVersion; // deprecated in favor of fullVersionList
  boolean wow64;
};

dictionary UALowEntropyJSON {
  sequence<NavigatorUABrandVersion> brands;
  boolean mobile;
  DOMString platform;
};

[Exposed=(Window,Worker)]
interface NavigatorUAData {
  readonly attribute FrozenArray<NavigatorUABrandVersion> brands;
  readonly attribute boolean mobile;
  readonly attribute DOMString platform;
  Promise<UADataValues> getHighEntropyValues(sequence<DOMString> hints);
  UALowEntropyJSON toJSON();
};

interface mixin NavigatorUA {
  [SecureContext] readonly attribute NavigatorUAData userAgentData;
};

Navigator includes NavigatorUA;
WorkerNavigator includes NavigatorUA;


CDDL 索引