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
これらの文字列には多くの情報(そしてかなりの虚偽情報)が詰め込まれています。バージョン番号、プラットフォームの詳細、モデル情報などがすべてリクエストごとに送信され、様々なフィンガープリンティング手法の基盤となっています。各ベンダーは自身のユーザーエージェント文字列の変更を試みてきましたが、歴史的な手法を妨げてきた開発者からのフィードバックにはいくつかのカテゴリがあります:
-
ブランドとバージョン情報(例: "Chrome 69")により、Webサイトは特定のリリースに存在する既知のバグを回避することができます。例えばContent Security Policyの実装はベンダーごとに大きく異なり、どのブラウザがパースと実行を担当するかを知らずにHTTPレスポンスにどのポリシーを送るべきか判断するのは困難です。
-
開発者はしばしばユーザーエージェントやプラットフォームに基づいて送信するコンテンツをネゴシエートします。例えば、あるアプリケーションフレームワークは、iOS上のアプリをAndroid上の同じアプリとは異なるスタイルにして、それぞれのプラットフォームの美学やデザインパターンに合わせます。
-
#1と同様に、OSのリビジョンやアーキテクチャが特定のバグの原因となり得るため、Webサイトのコードで回避策を取ることができ、ダウンロードする適切な実行ファイル(32bit/64bit、ARM/Intelなど)選択にも有用です。
-
高度な開発者はモデルやメーカー情報を使ってデバイスの能力(例: [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-PlatformとSec-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-Platform、Sec-CH-UA-Platform-Version、Sec-CH-UA-Arch、Sec-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リクエストヘッダーフィールドを定義します。以下の定義では、各ユーザーエージェントが自身のプロパティをいくつか定義していると仮定します:
-
ブランド - ユーザーエージェントの商用名称(例: "cURL", "Edge", "The World’s Best Web Browser")。32文字未満のASCII英字でなければなりません。
-
フォームファクター - デバイスのフォームファクター。従来はUser-Agent文字列内の<deviceCompat>トークンとして表現(例: "Tablet", "VR"など)。
-
フルバージョン - ユーザーエージェントまたはそのbrandsリスト内ブランドに対応するビルドバージョン(例: "72.0.3245.12", "3.14159", "297.70E04154A"など)。
-
モデル - ユーザーエージェントのデバイスモデル(例: "", "Pixel 2 XL"など)。
-
モバイル性 - ユーザーエージェントのデバイスがモバイルデバイスかどうかを示す真偽値(例: ?0 または ?1)。
-
プラットフォームブランド - ユーザーエージェントのOSの商用名(例: "Windows", "iOS", "AmazingOS"など)。
-
プラットフォームバージョン - ユーザーエージェントのOSバージョン(例: "NT 6.0", "15", "17G"など)。
-
プラットフォームアーキテクチャ - ユーザーエージェントのCPUアーキテクチャ(例: "ARM", "x86"など)。
-
プラットフォームビット数 - ユーザーエージェントのCPUアーキテクチャのビット数(例: "32", "64")。
-
重要バージョン - マーケティングバージョン(例: "72", "3", "12.1"など)。ユーザーエージェントまたはbrandsリスト内のブランドに対応し、ウェブで区別可能な機能を含む(例: レンダリングエンジンや同等クラスのフルバージョンなど)。
-
wow64性 - ユーザーエージェントのバイナリが64ビットWindows上で32ビットモードで動作しているかどうかを示す真偽値(例: ?0 または ?1)。
ユーザーエージェント はこれらの文字列を簡潔に保つべきですが、サーバーはそれぞれの値を任意に受け入れなければなりません。これらはすべて ユーザーエージェント の気まぐれで構築されます。
ユーザーエージェント は高エントロピーな プラットフォームアーキテクチャ の値を以下のバケットにマッピングしなければなりません:
-
x86 CPU アーキテクチャ => "x86"
-
ARM CPU アーキテクチャ => "arm"
他の CPU アーキテクチャは、状況によってこれらの値のいずれかにマッピングするか、空文字列にマッピングしてもかまいません。
ユーザーエージェント は、どちらも次の条件が当てはまるプラットフォーム以外では プラットフォームアーキテクチャ または プラットフォームビット数 の値として空文字列または架空の値を返すべきです:
-
実行可能ファイルのバイナリダウンロードが想定される。
-
異なる CPU アーキテクチャごとに異なるバイナリ実行ファイルリソースが必要とされ、またそれらのバイナリ実行ファイルリソースが利用可能であることが想定される。
ユーザーエージェントは mobileness が false の場合、model に対して空文字列を返さなければならない(MUST)。 また、ユーザーエージェントは mobileness が true であっても、通常モデルが公開されるプラットフォームを除き、 model に空文字列を返さなければならない(MUST)。
ユーザーエージェントは、以下のいずれかのヒントがリクエストされた場合、プライバシー、互換性、その他の理由により、
型sf-stringのヒントでは空文字列、型sf-booleanのヒントではfalse、または他の架空の値を返してもよい(MAY):
full
version、
platform architecture、
platform bitness、
wow64-ness、
model。
-
emulated client hints を、エミュレートされた UA クライアントヒントの environment settings に関連付けられているものとする。
-
emulated client hints が null でなく、かつ emulated client hints の property が未定義でない場合、 emulated client hints の property を返す。
-
property の実装定義値を返す。
3.1. 「Sec-CH-UA」ヘッダーフィールド
Sec-CH-UA リクエストヘッダーフィールドは、サーバーへ ユーザーエージェント の ブランドおよび 重要なバージョン 情報を提供します。これは Structured Header であり、その値は リスト [rfc9651] でなければなりません。リストの項目はすべて string
でなければなりません。それぞれの項目の値には ユーザーエージェント のバージョンを示す "v" パラメータを含めるべきです。
ヘッダーの ABNF は次の通りです:
Sec-CH-UA = sf-list
リクエストの Sec-CH-UA
値を返すために、次のステップを実行します:
-
brands を "significant version" で create brands を実行した結果とする。
-
list を brands と "significant version" で brand-version リストを作成する の結果とする。
-
リストのシリアライズ を 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"。該当するすべてのフォームファクター値を含めるべきです。
ユーザーエージェントのフォームファクターは、ユーザーがユーザーエージェントとどのようにやり取りするかを示します。許可されている値の意味は次の通りです:
-
"Desktop" はパーソナルコンピューターで動作するユーザーエージェントを指します。
-
"Automotive" は車両に組み込まれたユーザーエージェントを指し、ユーザーは車両の操作に責任があり、細かい操作に注意を払えない場合があります。
-
"Mobile" は通常ユーザーが身につける、小型でタッチ操作中心のデバイスを指します。
-
"Tablet" は "Mobile" よりも大きいタッチ操作中心のデバイスで、通常ユーザーが持ち歩かないものを指します。
-
"XR" はユーザーの周囲の環境を拡張または置換する没入型デバイスを指します。
-
"EInk" は画面更新が遅く、色再現が制限されているかないデバイスを指します。
-
"Watch" は非常に小さな画面(通常2 in未満)を持つモバイルデバイスで、ユーザーが素早くちらっと見られるように身につけるものです。
ユーザーが意味のある異なる方法で対話する新しいフォームファクターがある場合、またはサイトがそのデバイスでユーザーとのやり取りを変更したい強いユースケースがあり、既存のヒントでその新しいフォームファクターを確実に判別できない場合は、新しい値を提案し、仕様に追加する必要があります。
ヘッダーの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の値を返すには、次の手順を実行します:
-
brands に "full version" を指定して create brands を実行した結果を代入します。
-
list に brands と "full version" を用いて create a brand-version list を実行した結果を代入します。
-
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 が与えられたときに プラットフォームバージョンを取得するには、次の手順を実行する:
-
platform が "Linux" または "Fuchsia" の場合:
-
空文字列を返す。
-
-
platform が "Android" の場合:
-
platformReturnedVersionString に OS の
android.os.Build.VERSION.RELEASE文字列から取得した結果をセットする。 -
create a unified platform version string を platformReturnedVersionStringを引数にして実行した結果を返す。
-
-
platform が "iOS" の場合:
-
platformReturnedVersionString に
UIDeviceオブジェクトのsystemVersionを取得した結果をセットする。 -
create a unified platform version string を platformReturnedVersionString を引数にして実行した結果を返す。
-
-
platform が "Windows" の場合:
-
利用可能な場合(つまり、Windows 10 以上)、platformReturnedVersionString に
Windows.Foundation.UniversalApiContractの整数バージョンを取得し、文字列に変換した結果を代入する。それ以外の場合は、platformReturnedVersionString にレガシー Windows バージョン番号の取得の結果を代入する。 -
create a unified platform version string を platformReturnedVersionString を引数にして実行した結果を返す。
-
-
platformVersionComponentList を リストとして用意する。
-
platform が "macOS" の場合:
-
macOSVersion に
NSProcessInfoオブジェクトのoperatingSystemVersionプロパティを取得して代入する。 -
Append で macOSVersion の
majorVersion、minorVersion、patchVersionを(この順で)platformVersionComponentListに追加する。
-
-
platform がその他の場合:
-
concatenation を用いて、platformVersionComponentListを U+002E FULL STOP (
.) 区切りで結合したものを返す。
get the legacy Windows version numberは、次の手順を実行します:
-
OSVERSIONINFOのdwMajorVersionを major に代入します。 -
OSVERSIONINFOのdwMinorVersionを minor に代入します。 -
major が
6かつ minor が3(すなわち Windows 8.1)の場合、"0.3" を返します。 -
major が
6かつ minor が2(すなわち Windows 8)の場合、"0.2" を返します。 -
major が
6かつ minor が1(すなわち Windows 7)の場合、"0.1" を返します。 -
それ以外の場合は "0" を返します。
create a unified platform version stringは、文字列inputが与えられたとき、以下の手順を実行します:
-
platformVersionComponentList を リストとし、index を 0 に初期化します。
-
platformVersionUnprocessedTokenList を strictly splitting で input を U+002E FULL STOP (
.) で分割したリストとします。 -
index が 3 未満の間、次を繰り返します:
-
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 ; // deprecated in favor of fullVersionListuaFullVersion 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 brandsを significant versionで実行することで生成される リストです。
すべてのWindowOrWorkerGlobalScope
オブジェクトには、
関連付けられた
brands frozen arrayがある。
これは
FrozenArray<NavigatorUABrandVersion>
であり、
frozen arrayの作成
で
ユーザーエージェントの
brands
から生成される。
また、すべてのWindowOrWorkerGlobalScope
オブジェクトには
関連付けられた
full version list frozen arrayがある。
これは
FrozenArray<NavigatorUABrandVersion>
であり、
frozen arrayの作成
で
create brandsを
full
version
で実行した結果に対して生成されたものです。
4.1.2. brands の作成
create brandsにversion typeを指定して呼び出す場合は、次の手順を実行します:
-
listをリストとします。
-
Assert version typeが"full version"または"significant version"のいずれかであること。
-
brandごとに(それがユーザーエージェントや等価クラスを表す場合)、 brandについて:
-
versionをstringとして初期化し、次に従う:
-
もしversion typeが"full version"なら、versionを full version に対応する文字列とする。
-
もしversion typeが"significant version"なら、versionを significant version に対応する文字列とする。
-
-
dictを新しい
NavigatorUABrandVersion辞書として生成し、brandにbrandを、versionにversionを設定。 -
Appendでdictをlistへ追加。
-
-
ユーザーエージェントは次を実施すべき:
-
Appendでもう1件 itemをlistへ追加し、内容は
NavigatorUABrandVersion辞書(brandに arbitrary brandを、versionに create an arbitrary version(引数は version type)の結果)とする。 -
itemの順序をランダム化。
補足: これらのランダム成分を生成する際にキャッシュのばらつきを最小限に抑える1つの方法として、ビルド時に決定し、ユーザーエージェント の重要なバージョンの存続期間中は同一のままにしておくことが考えられる。
補足: これらのランダム化手順がいつ・なぜ適切となるかの詳細については、§ 8.2 GREASE風 UAブランドリスト を参照のこと。
-
-
listを返す。
equivalence classは互換性があるとみなされるブラウザーのグループを表します。たとえば共通のレンダリングエンジンを用いる場合、その equivalence class となります。
4.1.3. 任意ブランドとバージョン値の生成
arbitrary brand の作成のために、ユーザーエージェントは次を実行しなければなりません:
-
arbitraryBrand をASCIIアルファベットと0x20(SP)だけからなる文字列とし、0x20(SP)を1つ以上含み、かつ全長20ASCIIバイト以下、先頭末尾に0x20(SP)不可。
-
arbitraryBrandList にASCIIホワイトスペースで分割した配列を格納。
-
greaseyStack をstackとして用意。
-
greaseyChars をASCII bytes « 0x20 (SP), 0x28 (, 0x29 ), 0x2D -, 0x2E ., 0x2F /, 0x3A :, 0x3B ;, 0x3D =, 0x3F ?, 0x5F _ » のリストとする。
-
indexを0で初期化。
-
indexがarbitraryBrandListのサイズ−1未満の間:
-
greaseyBrandList をリストとしindex=0にする。
-
greaseyStackが空でない間:
-
AppendでarbitraryBrandList[index]をgreaseyBrandListに追加。
-
先頭・末尾の ASCII ホワイトスペースを除去し、その上で文字列連結(区切りなし)したgreaseyBrandListの結果を返す。
また、Structured Headersは0x22(\")や0x5C(\\)のエスケープも許しますが、これらはファイアウォールとの互換性問題も引き起こします。
arbitrary version の作成は、version typeを引数に次の手順を実施:
-
Assert version typeが"full version"または"significant version"どちらかであること。
-
arbitrary version をstringで初期化し次に従う:
-
もしversion typeが"full version"なら、arbitrary versionを full version の形式に一致する文字列とし、値自体は一致させない。
-
もしversion typeが"significant version"なら、arbitrary versionを significant version の形式に一致するが値は異なるものとする。
-
-
arbitrary versionを返す。
Note: ユーザーエージェントは必要に応じ、バージョンチェックが正しく行われるよう任意に低いバージョンを送信することができ、また適宜値を変化させるべきです。
4.1.4. ブランド-バージョンリスト作成
ブランド-バージョンリスト作成はbrandsとversion typeを与えて、次の手順を実行します:
-
list を リストとして初期化(空)。
-
Assert version typeは"full version"または"significant version"のいずれかであること。
-
brands内の各brandについて:
-
listを返す。
4.1.5. ゲッター
取得時、brands
属性はthisの関連グローバルオブジェクトのbrands frozen arrayを返さなければなりません。
取得時、mobile
属性はユーザーエージェントのmobilenessを返さなければなりません。
取得時、platform
属性はユーザーエージェントのplatform brandを返さなければなりません。
4.1.6. getHighEntropyValues メソッド
getHighEntropyValues(hints)
メソッドは以下の手順を実行しなければなりません:
-
pを新しい promiseとして現在のレルムで作成します。
-
uaDataを新しい
UADataValuesとして生成します。 -
uaData["
brands"]にthisの 関連グローバルオブジェクトの brands frozen array を設定します。 -
uaData["
mobile"]に ユーザーエージェントのmobilenessを設定します。 -
uaData["
platform"]に ユーザーエージェントのplatform brandを設定します。 -
もしthisの 関連グローバルオブジェクトの関連付けられた Documentがch-ua-high-entropy-values機能の 使用を許可されていない場合、pをuaDataで解決します。
-
そうでない場合、次の手順を並列で実行します:
-
もしhintsが"architecture"を含むなら、uaData["
architecture"]に ユーザーエージェントのplatform architectureを設定します。 -
もしhintsが"bitness"を含むなら、uaData["
bitness"]に ユーザーエージェントのplatform bitnessを設定します。 -
もしhintsが"formFactors"を含むなら、uaData["
formFactors"]に ユーザーエージェントのform-factorsを設定します。 -
もしhintsが"fullVersionList"を含むなら、uaData["
fullVersionList"]に thisの関連グローバルオブジェクトの full version list frozen arrayを設定します。 -
もしhintsが"model"を含むなら、uaData["
model"] に ユーザーエージェントのmodelを設定します。 -
もしhintsが"platformVersion"を含むなら、uaData["
platformVersion"] にplatform versionの取得(platform brandで)結果を設定します。 -
もしhintsが"uaFullVersion"を含むなら、uaData["
uaFullVersion"] -
もしhintsが"wow64"を含むなら、uaData["
wow64"] にユーザーエージェントのwow64-nessを設定します。 -
permission task sourceの タスクキューに resolve p with uaDataのタスクを入れる。
-
-
pを返します。
4.1.7. toJSON メソッド
toJSON() メソッドは次の手順を実行しなければなりません:
-
uaLowEntropyDataを新しい
UALowEntropyJSONとする -
uaLowEntropyData["
brands"] にthisの 関連グローバルオブジェクトのbrands frozen arrayを設定します。 -
uaLowEntropyData["
mobile"] にユーザーエージェントのmobilenessを設定します。 -
uaLowEntropyData["
platform"] にユーザーエージェントのplatform brandを設定します。 -
uaLowEntropyDataを返します
5. オートメーション
ユーザーエージェントの自動化およびアプリケーションテストの目的のために、本書は [WebDriver-BiDi] 仕様への拡張を定義する。
5.1. 定義
UserAgentClientHintsCommand = ( userAgentClientHints.SetClientHintsOverrideCommand )
A ブランドバージョンとは、以下を持つ構造体です:
ユーザーエージェントクライアントヒントとは、以下を持つ構造体です:
-
item(名前は full version): 文字列または未定義。初期値は未定義。
-
item(名前は mobile): 真偽値または未定義。初期値は未定義。
-
item(名前は model): 文字列または未定義。初期値は未定義。
-
item(名前は platform): 文字列または未定義。初期値は未定義。
-
item(名前は platform version): 文字列または未定義。初期値は未定義。
-
item(名前は architecture): 文字列または未定義。初期値は未定義。
-
item(名前は bitness): 文字列または未定義。初期値は未定義。
-
item(名前は wow64): 真偽値または未定義。初期値は未定義。
remote end には関連付けられた emulated client hints がある。これは struct であり、次のものを持つ:
-
item(名前は default emulated client hints): user agent client hints または null。初期値は null。
-
item(名前は emulated client hints per user contexts): user context から user agent client hints への弱いマップ。初期値は空。
-
item(名前は emulated client hints per navigables): navigables から user agent client hints への弱いマップ。初期値は空。
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= {}
-
related navigables を 関連する navigable の取得 の environment settings での結果とする。
-
related navigables のそれぞれの navigable について:
-
top-level navigable を navigable の トップレベルトラバーサブルとする。
-
user context を top-level navigable の 関連付けられたユーザーコンテキストとする。
-
もし emulated client hints の navigableごとの emulated client hints が top-level navigable を含むならば、emulated client hints の navigableごとの emulated client hints[top-level navigable] を返す。
-
もし emulated client hints の ユーザーコンテキストごとの emulated client hints が user context を含むならば、emulated client hints の ユーザーコンテキストごとの emulated client hints[user context] を返す。
-
-
default emulated client hints を emulated client hints の デフォルトの emulated client hints とする。
-
もし default emulated client hints が null でなければ、 default emulated client hints を返す。
-
null を返す。
remote end の手順(command parameters与えられた場合)は次の通り:
-
もし command parameters が "userContexts" を含み かつ command parameters が "contexts" を含む場合、 error を error code invalid argument で返す。
-
emulated client hints を command parameters["
clientHints"] とする。 -
もし command parameters が "contexts" を含むなら:
-
navigables を try での ID指定で有効なトップレベルトラバーサブルの取得 の command parameters["
contexts"] を適用した結果とする。 -
各 navigable について:
-
もし emulated client hints が null なら navigable を emulated client hints の navigable ごとの emulated client hints から削除する。
-
そうでなければ、set で emulated client hints の navigable ごとの emulated client hints[navigable] に emulated client hints をセットする。
-
-
success を data null で返す。
-
もし command parameters が "userContexts" を含むなら:
-
user contexts を try の 有効なユーザーコンテキスト取得 の command parameters["
userContexts"] での結果とする。 -
各 user context について:
-
もし emulated client hints が null なら user context を emulated client hints の ユーザーコンテキストごとの emulated client hints から削除する。
-
そうでなければ、set で emulated client hints の ユーザーコンテキストごとの emulated client hints[user context] に emulated client hints をセットする。
-
-
success を data null で返す。
-
セットで emulated client hints の デフォルトの emulated client hints に emulated client hints を設定する。
-
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リストの標準的な処理を促すことができます。 ランダムかつ恣意的順序で、追加かつ意図的に間違えたカンマ区切り値を含めれば、特定値だけに依存する事態を減らせます。
いくつかの例を見てみましょう:
-
未知のブラウザが許可リストから排除されるのを防ぐため、Chromeは一時的に実在しないブラウザ名を含むUAセットを送信できます。
-
"Chrome"; v="73", "(Not;Browser"; v="12"
-
-
Chromiumバージョンに基づく同値クラスを可能にするため、Chromeはレンダリングエンジンおよびそのバージョンもそれに加えられます。
-
"Chrome"; v="73", "(Not;Browser"; v="12", "Chromium"; v="73"
-
-
サイトが正確なUAスニフィングでなくChromiumバージョンベースの同値クラスを頼りにするよう促すため、Chrome自身をセットから除外することもできます。
-
"(Not;Browser"; v="12", Chromium"; v="73"
-
-
Chromiumベースのブラウザは類似のUA文字列を用いても自ブランドをリストの一部に使うことで、サイトがそれらをカウント可能にできます。
-
"Chrome"; v="73", "Xwebs mega"; v="60", "Chromium"; v="73", "(Not;Browser"; v="12"
-
ユーザーエージェントは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-UA、Sec-CH-UA-Arch、
Sec-CH-UA-Bitness、
Sec-CH-UA-Form-Factors、Sec-CH-UA-Full-Version、Sec-CH-UA-Mobile、
Sec-CH-UA-Model、
Sec-CH-UA-Platform、Sec-CH-UA-Platform-Version、Sec-CH-UA-WoW64、
Sec-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