1. 序論
開発者は、自身のページのコンテキストに読み込まれるリソースと、 そのページがリクエストを行えるエンドポイントを制御したいと考えている。この制御は、 ユーザーのデータがユーザーエージェントを通じて流れる方法を制限すること(データ流出攻撃の緩和)や、 サイトのアーキテクチャと依存関係を確実に制御することを含む、いくつかの目的に必要である。
Content Security Policy はこの必要性の一部に対処しているが、最も重要なユースケースに必要なものよりも 細粒度な方法で行っており、また CSP がデプロイに用いられる他の保護によって複雑化した構文と文法を持つ。 [CSP]
`Connection-Allowlist`
は CSP から一歩引き、ページが Fetch および他の Web プラットフォーム API(WebRTC、Web
Transport、FedCM、Web Payments、DNS Prefetch など)を通じて開始できる明示的なリクエストを、
単純明快かつ包括的であることを目指す方法で制御するという、単一のユースケースに焦点を当てる。
注: '\' による行折り返しは RFC 8792 に従う
Connection-Allowlist: (response-origin "https://cdn.example" "https://*.example.:tld" \
"https://api.example:*"); report-to=ReportingAPIEndpoint
ユーザーがナビゲートした文書とともに配信されるこのヘッダーは、
その文書を、リストで指定された URL パターン
[URLPATTERN]
に一致するエンドポイント、すなわちその文書が配信されたオリジン、
https://cdn.example、DNS ラベルの末尾から 2 番目が
example である任意のホストの任意のサブドメイン、
任意のポート上の https://api.example、などに対するリクエストと接続だけを
許可するよう制限する。
許可リストに一致しないエンドポイントへの接続の試みはブロックされ、
report-to パラメーターで指定された Reporting API
[REPORTING] endpoint
(別個の Reporting-Endpoints ヘッダーを通じて定義される)を介して報告される。
1.1. 脅威モデル
この提案は意図的に小さく、クライアントサイド攻撃および/または誤設定の、 具体的だが有用なニッチを対象としている:
-
文書およびワーカー向けのポリシーは、サーバーによって HTTP レスポンスヘッダーとして表明される。 これは、レスポンスヘッダーを操作できる攻撃者は引き続きスコープ外であることを意味する。
-
文書(またはワーカー)の表明されたポリシーは、_その_ コンテキストによって開始されたリクエストのみを支配する。 フレーム化された文書が別個のポリシーを表明するなら、それはそれでよい(ただし、このポリシーは ローカルスキーム(
data:、about:など)を介して作成されたコンテキストにも適用されるという注意点がある)。 これは、新しい文書/ワーカーコンテキストを作成する際に HTML によって処理される、コンテキストの policy container の他の構成要素と同様である。 -
この提案が防御しようとする脅威は、接続および/またはリクエストである。データ流出防御として有効であるためには、 接続が行われる前に接続をブロックしなければならない。
-
その他の優れた Web プラットフォーム API の意図しない影響として利用可能なサイドチャネルは非常に多い。 この提案はそれらに対処しようとはせず、ページのためにユーザーエージェントによって明示的に開始される リクエストまたは接続のみに焦点を当てる。これには明らかに、
fetch()およびXMLHttpRequestの明確なケースに加え、 一般的なリソースリクエストも含まれる。また、より明示的には「リクエスト」ではないチャネルを通じて確立される ネットワーク接続も含まれる。すなわち、Web Install API を通じてフェッチされるマニフェスト、WebRTC による TURN/STUN サーバーへの接続、Web Transport チャネル、DNS プリフェッチ、ナビゲーションなどである。 これらはすべてスコープ内であり、一方でメモリや CPU 消費、ソケット枯渇、一般的な XSLeaks のような より難解なチャネルはスコープ外である。 -
この提案は通信チャネルのみを扱う。コンテンツ注入やクロスサイトスクリプティングのような脅威を 防止する(あるいは実質的に緩和する)ことを目的としていない。そのような攻撃の影響を、 ポリシーが適用されている_それらの特定のページ_でのみ制約できるにすぎず、 ページの防御における 1 つの層としてのみ考えるべきである。それ自体では十分ではない。
-
オープンリダイレクトのようなサーバーサイド脅威の一部に対して防御を試みることは魅力的である。 クライアントを離れたデータは基本的にサーバーの制御下に入るため、効果的な方法でそうすることには苦労するだろう。 とはいえ、リダイレクトレスポンスを通じて他のサーバーへの接続を作成するというサーバーの決定に、 クライアントが直接協力するかどうかを開発者が選択できるようにするのは合理的に思われる。 今後より細かな粒度が必要になった場合に拡張の余地を残しつつ、2 つの選択肢を提供する。 デフォルトでは、宛先に関係なくリダイレクトレスポンスはブロックされる。開発者は、ヘッダーに パラメーターを設定することで、すべてのリダイレクトレスポンスを許可することを選択できる。 詳細は § 6.7 リダイレクト を参照。
-
同様に、WebRTC 接続は、動的なエンドポイント発見やピアツーピア接続を伴うことが多いため、 URL パターンによって制約することが難しい。開発者が WebRTC 接続を完全に許可するかブロックするかを 選択できるように、グローバルトグルを提供する。詳細は § 6.8 WebRTC を参照。
1.2. Content Security Policy との重複
この提案は、特定のコンテキスト内でのリソース利用に対する制限についての Content Security Policy のアプローチ、 特に fetch directives と多くの共通点を持つ。それでもなお、 いくつかの理由から検討する価値があるように思われる:
-
CSP のモデルは細かすぎる: 機密性の高いコンテキストからデータが流出するリスクを緩和したい開発者は、 リクエストの発行や接続の確立が可能な方法を網羅的にカバーする保護を必要とする。 CSP による、リクエストを個別に制御できる種類へ分類する方法は、この問題に取り組む方法としては誤っている。 Web フォントのリクエストを通じたデータ漏洩は、画像やスクリプトのリクエストを通じたデータ漏洩と同じくらい悪いからである。 これらのリクエスト種別を区別すると、単に無関係な疑問によって、合理的な防御を設計する過程が複雑化する。
-
CSP の構文は十分に粒度が細かくない: CSP がサポートする
host-source文法は、レスポンスとともに配信される ヘッダーを本当に冗長なものにする。別個のポリシーは、URLPattern 構文へ移行する機会を提供する。 これは、より現代的で、柔軟で、標準化された照合構文を提供することで、CSP のアプローチに関して人々が提起してきた いくつかの不満を解決するだろう。 -
CSP のカバレッジは不完全である: CSP は Fetch を通る HTTP リクエストをうまくカバーしているが、 Web プラットフォーム API が接続の確立を可能にする無数の方法を網羅的にカバーしているわけではない。 DNS プリフェッチと WebRTC は取りかかるべき良い例だが、CSP の脅威モデルにどのように適合するのかに まさに苦慮してきたものは他にも多い。狭い焦点と開発者への明示的な約束を持つ新しいポリシーを作成することで、 これらの議論には防御可能な答えと、仕様作成者への明確な権限が与えられるだろう。
2. 接続許可リスト
Connection Allowlist は、特定のコンテキストが接続を許可される URL patterns の集合を表す。 これは、以下の items を持つ struct である:
-
allowlist。これは list の URL patterns である。 別途指定されない限り、空のリストである。
-
reporting endpoint。これは
nullまたは Reporting API endpoint のいずれかである。別途指定されない限りnullである。 -
disposition。これは enforce または report のいずれかである。
-
redirects。これは allow または block のいずれかである。別途指定されない限り、 block である。
-
webrtc。これは allow または block のいずれかである。別途指定されない限り、 block である。
3. Connection Allowlist ヘッダー
Connection-Allowlist レスポンス header は、 コンテキストが接続を許可されるエンドポイントの集合を定義する、シリアライズされた URL パターン文字列のリストを含む。 この許可リストは特定のコンテキストに対して強制され、表明されたパターンに一致しない発信接続をブロックする。 Connection-Allowlist-Report-Only レスポンス header は report-only 変種であり、同じ方法で構文解析されるが、 発信接続をブロックせずに違反レポートのみを送信する。
これらの Connection Allowlist ヘッダーは structured headers であり、その値は list の inner lists である。サーバーは任意の数の項目を含むリストを配信してよいが、 最初の項目だけが使用される。リスト内の追加の項目はすべて無視される。
inner list には、strings
としてシリアライズされた URL Patterns、または
token
response-origin のいずれかを含めることができる。
これは response の URL の
origin に一致するパターンを表す。予期しない値は無視される。
inner list は任意の parameters を持ってよい:
-
report-toパラメーターの値は、 Reporting API endpoint [REPORTING] を表す token として構文解析される。 -
redirectsパラメーターの値は、 token として構文解析される。存在する場合、それは許可リストの redirects を設定するために使用される。 値が tokenblockである場合は block に設定され、 それ以外の場合は allow に設定される。 -
webrtcパラメーターの値は、 token として構文解析される。存在する場合、それは許可リストの webrtc を設定するために使用される。 値が tokenblockである場合は block に設定され、 それ以外の場合は allow に設定される。
その他すべてのパラメーターは無視される。
3.1. 構文解析
-
allowlists を空の list とする。
-
header を、response の header list から、 `
Connection-Allowlist` という名前の structured field value を取得した結果とし、 それを list として扱う。 -
header、response の URL、および enforce が与えられたものとして、 Parse a Connection Allowlist header する。結果が
nullでない場合、それを allowlists に insert する。 -
header を、response の header list から、 `
Connection-Allowlist-Report-Only` という名前の structured field value を取得した結果とし、 それを list として扱う。 -
header、response の URL、および report が与えられたものとして、 Parse a Connection Allowlist header する。結果が
nullでない場合、それを allowlists に insert する。 -
allowlists を返す。
-
list の size が 0 である場合、
nullを返す。 -
list[0] が inner list でない場合、
nullを返す。 -
allowlist を、その disposition が disposition である Connection Allowlist とする。
-
list[0] 内の各 item について For each:
-
serialized pattern を
nullとする。 -
item が token
response-originである場合:-
serialized pattern を、response-url の origin の ASCII serialization に設定する。
-
-
item が string である場合、 serialized pattern を item に設定する。
-
serialized pattern が
nullである場合、 continue する。 -
URL pattern を、
nullを基底 URL として serialized pattern が与えられたものとして build a URL pattern from an HTTP structured field value を実行した結果とする。このステップがエラーを投げる場合、 continue する。
-
-
list[0] の parameters 内の各 key → value について For each:
-
key が
report-toであり、value が token である場合、allowlist の reporting endpoint を value に設定する。
-
-
allowlist を返す。
注: 構文解析アルゴリズムでは、 無効な入力をすべて飛ばしている。もっと厳格な構文解析を行うことも十分あり得るが、 それは将来の柔軟性を制限する可能性が高い。
3.2. 照合
確立される接続の種類によっては、処理対象となる request がある場合もあれば、
URL
しかない場合、あるいはそれより少ない情報しかない場合もある。
たとえば dns-prefetch は、
ホストに対してのみ照合できる。以下のアルゴリズムは、これらのシナリオで接続許可リストのチェックがどのように機能するかを規定する:
-
connection allowlist の allowlist 内の各 pattern について For each:
-
input を新しい
URLPatternInitdictionary とし、そのhostnameを pattern の hostname component に設定する。 -
host-only pattern を、 input、基底 URL としての
null、および options としての空の map が与えられたものとして creating a URL pattern した結果とする。 -
synthetic url を、 "https://" と host を連結したものを URL として parsing した結果とする。
-
host-only pattern と synthetic url が与えられたものとして URL pattern matching が
nullを返さない場合、success を返す。
-
-
failure を返す。
注: hostname component だけを持つ新しいパターンを作成し、 host 用の URL を合成することで、 任意のプロトコル、任意のポート、任意のパスなどでそのホストへのリクエストを許可し得るパターンが 許可リスト内に_少しでも_存在すれば、一致を返すことができる。
-
connection allowlists 内の各 connection allowlist について For each:
-
url、environment、および connection allowlist が与えられたものとして Report a violation する。
-
connection allowlist の disposition が enforce である場合、 blocked を返す。
-
allowed を返す。
-
allowlists を、request の policy container の connection allowlists とする。
-
allowlists 内の各 allowlist について For each:
-
request の URL list の size が 1 より大きい場合:
-
request の url、request の client、および allowlist が 与えられたものとして Report a violation する。
注: リダイレクトが ブロックされる場合、リダイレクト先について必要以上の情報を漏らすことを避けるため、 意図的に request の url を報告し、その current url は報告しない。
-
allowlist の disposition が enforce である場合、 blocked を返す。
-
Continue する。
-
request の url、request の client、および allowlist が 与えられたものとして Report a violation する。
-
allowlist の disposition が enforce である場合、 blocked を返す。
-
-
allowed を返す。
-
connection allowlists 内の各 connection allowlist について For each:
-
host が connection allowlist に host-matches する場合、 continue する。
-
host、environment、および connection allowlist が与えられたものとして Report a violation する。
-
connection allowlist の disposition が enforce である場合、 blocked を返す。
-
-
allowed を返す。
-
allowlists を、environment の policy container の connection allowlists とする。
-
allowlists 内の各 allowlist について For each:
-
"
webrtc"、environment、および allowlist が与えられたものとして Report a violation する。 -
allowlist の disposition が enforce である場合、 blocked を返す。
-
allowed を返す。
3.3. 報告
他のポリシー機構と同様に、Connection Allowlists は、許可リストヘッダーで指定された Reporting API エンドポイントへ各違反を報告する。違反は、次の dictionary 型によって表される:
enum {ConnectionAllowlistDisposition ,"enforce" };"report" dictionary :ConnectionAllowlistViolationReport ReportBody {USVString ;url USVString ;connection sequence <DOMString >;allowlist ConnectionAllowlistDisposition ; };disposition
ConnectionAllowlistViolationReport
の
connection
は、許可リストに違反した接続の、シリアライズされた
URL
である。
ConnectionAllowlistViolationReport
の
allowlist
は、違反された
allowlist である。
ConnectionAllowlistViolationReport
の
disposition
は、allowlist
の
disposition である。
webrtc" (resource URL)、environment (environment)、および
connection
allowlist (allowlist) が与えられたとき、
report a violation するには、次を行う:
-
allowlist の reporting endpoint が
nullである場合、返す。 -
violation を、新しい
ConnectionAllowlistViolationReportとし、次のように初期化する:
url-
environment の creation URL を、 stripped for use in reports したもの。
connection-
resource URL が URL である場合、 resource URL を stripped for use in reports したもの。
それ以外の場合、resource URL。
allowlist-
allowlist の allowlist 内の各パターンをシリアライズした結果を含む新しいリスト
disposition-
allowlist の disposition。
-
environment をコンテキストとして、"
connection-allowlist" を type として、allowlist の reporting endpoint を destination として、そして violation を data として与え、 Generate and queue a report する。
4. 埋め込み適用
文書は、他のサーバーによって配信されるコンテンツを埋め込むことが多く、その埋め込まれた
コンテンツが少なくとも自身の要件と同程度に制約されることを保証しようとします。
`Connection-Allowlist`
ヘッダーを使用すると、
サーバーは自身の接続を制約できますが、埋め込み元は、フレーム化する文書に適用される
接続許可リストを制御できません。
この節では、[csp-embedded-enforcement]をモデルとしたオプトイン
メカニズムを定義します。これにより、埋め込み元は、フレーム化された文書に特定の
接続
許可リストを要求できます。
埋め込み元は、フレームに要求する接続許可リストを、
connectionAllowlist
コンテンツ属性を介して宣言します。ユーザーエージェントは、
`Sec-Required-Connection-Allowlist`
リクエストヘッダーで、
フレーム化された文書に要件を伝達します。
フレーム化された文書は、要件を
満たす
`Connection-Allowlist`
を表明するか、埋め込み元のオリジンを指定する
`Allow-Connection-Allowlist-From`
レスポンスヘッダーを返すことで、この要件にオプトインします。
ローカルスキームから配信される文書
(about:srcdocやdata:など)は、埋め込み元の
ポリシーコンテナーを継承するため、暗黙的にオプトインします。
オプトインしないフレームはブロックされます。
フレームがオプトインすると、要求された接続許可リストは、文書が自身について表明する許可リストとともに、フレーム化されたDocumentの ポリシーコンテナーに追加されます。また、この要件は 要求された接続許可リストを介して、 フレームの子孫に継承されます。
https://good.exampleおよびウィジェット自身の
オリジンのみに制約します:
< iframe connectionAllowlist = '("https://good.example" response-origin)' src = "https://widget.example/" ></ iframe >
ユーザーエージェントは、ナビゲーションリクエストとともに要件を送信します:
GET / HTTP / 1.1 Host : widget.example Sec-Required-Connection-Allowlist : ("https://good.example" response-origin)
ウィジェットは、埋め込み元のオリジンを承認することでオプトインするか...
Allow-Connection-Allowlist-From: https://embedder.example
...または、要件を満たす 接続許可リストを表明することでオプトインします:
Connection-Allowlist: ("https://good.example" response-origin)
どちらの場合もフレームは読み込まれ、結果として得られるDocumentは、
https://good.exampleおよび自身のオリジンのみに制約されます。ウィジェットがどちらのヘッダーも返さず
(かつローカルスキームから配信されていなかった)場合、
フレームはブロックされます。
4.1.
connectionAllowlist 属性
partial interface HTMLIFrameElement { [CEReactions ]attribute DOMString connectionAllowlist ; };
connectionAllowlist コンテンツ属性は、
埋め込み元がiframeによってフレーム化される
Documentに要求する
接続
許可リストを指定します。その
値は、
`Connection-Allowlist`
ヘッダーと同じ文法を使用します。すなわち、内部リストの
構造化ヘッダー
リストです(§ 3 接続許可リストヘッダーを参照)。
connectionAllowlist IDL 属性は、
connectionAllowlist コンテンツ属性を
反映しなければなりません。
注: 文書が自身に適用する、サーバーによって表明された
`Connection-Allowlist`
とは異なり、
connectionAllowlist 属性は埋め込み元によって設定され、別の文書に適用されます。
埋め込み元が、同意しないクロスオリジンコンテンツにポリシーを暗黙的に課すことを
防ぐため、フレーム化された文書はオプトインしなければなりません。§ 4.4 要件の取得と適用を参照してください。
4.2. 埋め込み適用ヘッダー
Sec-Required-Connection-Allowlist
リクエストヘッダーは、
埋め込み元がフレーム化された文書に要求する接続許可リストを伝達します。その値は、
`Connection-Allowlist`
文法を使用する
構造化ヘッダーのリストです。
名前にSec-プレフィックスが付いているため、これは禁止リクエストヘッダーであり、ユーザーエージェントのみが設定でき、
スクリプトによって設定または変更することはでき、
スクリプトによって設定または変更することはできません。
Allow-Connection-Allowlist-From
レスポンスヘッダーを使用すると、
文書は、埋め込み元が要求された接続許可リストを自身に適用することに
オプトインできます。これは
Allow-CSP-Fromと
文法および比較方法を共有し、Fetch が
Access-Control-Allow-Originを照合するのと同様に、埋め込み元のオリジンを正確に照合します:
Allow-Connection-Allowlist-From = [=origin-or-null=] / [=wildcard=]
-
originを、responseのヘッダーリストから `
Allow-Connection-Allowlist-From` を 取得した結果とします。 -
originが
`*`である場合、true を返します。 -
requestを使用してリクエストオリジンをバイト直列化した結果が originである場合は true を返し、 それ以外の場合は false を返します。
注: これはAllow-CSP-Fromおよび CORS チェックを反映しています。ヘッダーは、埋め込み元の 直列化されたリクエストオリジン (またはワイルドカード)とバイト単位で比較され、 URLとしても、オリジンとしても、まったく解析されません。
4.3. 許可リストの比較
構造体の等価性は、 まだ明確に定義されていません。ここでは、2つのURL パターンが 同じ直列化された文字列から 作成された場合、それらは等しいものとします。(whatwg/infra#710も参照してください。)[whatwg/infra Issue #664]
注: これは(狭義ではない)部分集合関係です。 a内のすべてのURL パターンがbに現れる必要がありますが、 aとbは等しくてもかまいません。したがって、要件とまったく同じ内容を表明するレスポンスは、 その要件を満たします。
注: 上記の比較では、レスポンスが表明した URL パターンが要件内に存在することのみが要求され、 それらのパターンが論理的に包含されるかどうかを判断する意味的な分析は行われません。 これは意図的なものです。あるURL パターンが別のものを完全に 包含するかどうかを判断することは、その構文を考慮すると困難な問題であり、保守的な集合所属判定で、 現在の開発者のユースケースには十分だからです。
注: 比較される許可リストは同じ
URLを基準に解決されるため、
response-origin トークンは
それぞれで同一に解決されます。
-
requirementのリダイレクトが blockである場合、 candidateの リダイレクトもblockであること。
-
requirementのwebrtcが blockである場合、 candidateの webrtcもblockであること。
注: 空のcandidateの許可リストは、どのエンドポイントも許可せず、 (すべての許可リストの部分集合であるため) リダイレクトおよび WebRTC の処理も満たす任意の要件を満たします。
注: 「満たす」は、 この節全体で使用される「少なくとも同程度に厳格である」という関係を表します。 許可リストの比較(部分集合である)はURL パターンを処理し、 リダイレクトおよびwebrtcの処理は、 個別の条件として扱われます。
4.4. 要件の取得と適用
ポリシーコンテナー
構造体に、要求された接続許可リスト項目を追加します。これは、
nullまたは文字列
(`Connection-Allowlist`
ヘッダー文法で表現された直列化済みの要件)のいずれかであり、初期値はnullです。これは、
コンテキストが自身の埋め込む文書(およびワーカー)に課す要件を表します。この要件は、
ポリシーコンテナーがそれらのコンテキストにコピーされる際に、
ローカルスキームの文書およびワーカーによって直接継承されます。そのため、制約されたコンテキストが、
より制約の緩い子を埋め込むことで制約から逃れることはできません。
注: 要件は、解決済みの接続許可リストとしてではなく、直列化された文字列として保存されます。これにより、
要件がフレームツリーを下って継承される際に、response-origin トークンが、
フレーム化された各レスポンスのURLを基準として個別に解決されます。
埋め込み元で一度だけ解決すると、response-originが埋め込み元のオリジンに固定され、
子孫に誤って適用されます。これは[csp-embedded-enforcement]を反映しています。これも同様に、
要件をポリシーコンテナー上に直列化された形式で保存し、
適用時にのみ解析します。
注: 要件をDocument上ではなく、 ポリシーコンテナー上に保存することは、 [csp-embedded-enforcement]における、 類似のポリシーコンテナー項目の扱いに従っています。また、これによって同じメカニズムで ワーカーも制約できます。
-
containerを、navigableのコンテナーとします。
-
parent requiredを、containerのノード文書のポリシーコンテナーの 要求された接続 許可リストとします。
-
containerが、 値(attribute value)が空文字列ではない
connectionAllowlistコンテンツ属性を持つiframe要素であり、かつattribute valueがparent requiredに対して 有効な connectionAllowlist 属性値である場合、 attribute valueを返します。 -
parent requiredを返します。
文字列(value)は、次のすべてが true である場合、 要件parent requiredに対する有効な connectionAllowlist 属性値です:
-
valueが空文字列ではないこと。
-
valueの長さが4096以下であること。
注: 4096という制限は、直列化された要件を `
Sec-Required-Connection-Allowlist` リクエストヘッダーで伝送できる程度に小さく保ち、 フレームツリーを下って継承される際に無制限に増大するのを防ぐための任意の上限です。 正確な値自体に重要な意味はありません。 -
parent requiredが
nullであるか、valueが parent requiredと少なくとも同程度に厳格であること。
注: フレームは、親から継承した要件を厳しくすることはできますが、
緩めることはできません。
connectionAllowlist属性は、親の要件と少なくとも同程度に厳格である場合にのみ尊重されます。
そうでない場合、親の要件が変更されずに継承されます。これは、
[csp-embedded-enforcement]における、
iframe
のcsp属性が埋め込み元自身の要件に包含されなければならないという
有効性要件を反映しています。
response-origin
トークンは、URLを基準に解決されるのではなく、
文字列「response-origin」から構築されたリテラルのURL パターンとして扱われます。
注: この比較はナビゲーション時に、
response-originを
いずれかのURLを基準に解決することなく実行されます。
埋め込み元の要件とフレーム自身の要件は、後でそれぞれ同じフレーム単位の
レスポンスのURLを基準に解決されるため、
ここでトークンを自身と等しいものとして扱うことは妥当であり、クロスオリジンリダイレクトによって変更され得る
URLへの依存を回避できます。この比較は保守的です。属性が構文上、
親の要件と少なくとも同程度に厳格でないフレームは、その要件を変更せずに継承します。
-
listが失敗である場合、
nullを返します。 -
list、response-url、およびdispositionを指定して Connection Allowlist ヘッダーを解析した結果を返します。
null(requirement)を指定し、
許可または
ブロックを返します:
-
requirementが
nullである場合、許可を返します。 -
requiredを、requirement、responseのURL、および enforceを指定して 直列化された接続許可リスト 要件を解析した結果とします。
-
requiredが
nullである場合、許可を返します。注: 不正な形式の要件は、 フレームをブロックするのではなく無視されます。
-
responseがrequestからの接続許可リストを許可する場合、 許可を返します。
-
headerを、responseのヘッダーリストから、 `
Connection-Allowlist` という名前の"list"として 構造化フィールド値を取得した結果とします。 -
assertedを、header、responseのURL、および enforceを指定して Connection Allowlist ヘッダーを解析した結果とします。
-
assertedが
nullではなく、assertedが requiredを満たす場合、 許可を返します。注: 不正な形式で表明された `
Connection-Allowlist` はnullに解析されるため、オプトインとして扱われません。 -
ブロックを返します。
注: ローカルスキームの文書
(about:srcdocやdata:など)には
レスポンスがなく、このチェックを通過しません。これらは、埋め込み元の
ポリシーコンテナー
(保存されている要件を含む)を直接継承します。§ 5.2 HTML との統合を参照してください。
5. モンキーパッチ
5.1. Fetch との統合
同じ目的を果たす他のチェックとともに、Fetch § 4.1 メインフェッチにブロックチェックを追加することで、リクエストを処理します:
-
不正なポートが原因でリクエストをブロックすべきか、リクエストのフェッチを混在 コンテンツとしてブロックすべきか、コンテンツセキュリティポリシーによってリクエストをブロックすべきか、 接続 許可リストによってリクエストをブロックすべきか、 または整合性ポリシーポリシーによってリクエストをブロックすべきかが blocked を返す場合、response をネットワークエラーに設定します。
Fetch は、リクエストに基づかない API の接続を確立するために使用される、 より低レベルのアルゴリズムも定義しています。DNS プリフェッチや Web Transport などを処理するため、オリジンを 解決するおよび接続を取得するにフックします:
上記のホストのみの照合アルゴリズムを呼び出し、いずれかのパターンが指定されたホストへの接続を 許可する可能性があるかどうかを判定する。そうでない場合、解決を失敗させる。
Document
environment(既定値は null)を受け入れるようにシグネチャを更新する:
現在のステップ 2 の前に、次の検査を追加する:
-
environment が null でない場合:
-
URL を 接続許可リストによってブロックすべきかを、url、environment、および allowlists に対して実行したとき、ブロック済み を返す場合、失敗を返す。
Fetch への変更では、 使用すべき許可リストと、報告に使用すべきコンテキストを識別するため、低水準 アルゴリズムの呼び出し箇所に追加情報を渡す必要がある。代わりに、それらの呼び出し箇所自体に 検査を実行させる方がよいかもしれない。ロジックを一元化する方が成功する可能性は高いと思うが、 個別に対応する方が単純かもしれない。
5.2. HTML との統合
上記を HTML に統合するため、ポリシーコンテナ 構造体に、新しい 接続許可リスト項目を追加する。この項目には、接続許可リストのリストが含まれる。これは、 フェッチ応答からポリシーコンテナを 作成するアルゴリズムに手順を追加することで設定される:
-
response と result を使用して Integrity-Policy ヘッダーを解析する。
- result の接続許可リストを、 response を与えて 応答の Connection Allowlists を解析した 結果に設定する。
-
result を返す。
注記: Early Hints リンクをフェッチするときには、早期応答の ポリシーコンテナがすでに使用されるため、Early Hints の統合にさらなる 変更は必要ない。
§ 4 埋め込み強制をサポートするため、[csp-embedded-enforcement]が 必須 CSP に使用するモデルに従い、埋め込み要素からの埋め込み側の要件を、 ターゲットスナップショットパラメーターおよびナビゲーションパラメーターを介して、フレーム内のDocumentの ポリシーコンテナへ伝播させる。具体的には、HTML と Fetch を次のように修正する:
-
必須接続許可リスト 項目を、ポリシーコンテナ 構造体に 追加する(§ 4.4 要件の取得と強制で 定義される)。
-
nullまたは文字列のいずれかである必須接続許可リスト項目を、 ターゲットスナップショットパラメーター構造体に追加する。HTML の ターゲットスナップショットパラメーターをスナップショットする アルゴリズムは、この項目を、ターゲットナビガブルを与えて 必須接続 許可リストを決定する結果に設定する。 -
対応する項目を、ナビゲーションパラメーター構造体に追加し、ナビゲートする、 フェッチによってナビゲーションパラメーターを作成する、および srcdoc リソースから ナビゲーションパラメーターを作成するは、 ターゲットスナップショットパラメーター項目からこれを設定する。
-
フェッチによってナビゲーションパラメーターを作成するは、 リクエストを作成した後、その項目が
nullでない場合、リクエストのヘッダーリスト内の `Sec-Required-Connection-Allowlist` ヘッダーを、 ターゲットスナップショットパラメーター項目に設定する。 -
フェッチ応答から ポリシーコンテナを作成するは、追加の 引数として要件を受け取り、result の接続許可リストを設定した後、以下の 必須接続 許可リストを適用する手順を実行する。
注記: ターゲットスナップショットパラメーターですでに保持されるサンドボックス化フラグと同様に、要件は
ナビゲーション時に
iframe
コンテナーから、フレーム内のDocument
自身が開始するものを含む、ナビガブルのすべての
ナビゲーションについてスナップショットされる。したがって、この制約は後続の同一ナビガブルのナビゲーションにも適用され、フレーム内コンテンツが
自身を別の場所へナビゲートすることで回避することはできない。connectionAllowlist 内容
属性への変更は、ナビガブルの次回のナビゲーション時に有効となり、sandbox 属性の
動作を反映する。(これは、コンテナー自身が開始するナビゲーションにのみ影響する
referrerpolicy とは異なることに注意されたい。)
注記: 埋め込み側の接続許可リストは、
応答が自身について表明したもの(
`Connection-Allowlist-Report-Only`
を含む)と並ぶ追加の項目として、
result の
接続許可リストに追加される。
そのリスト内の各許可リストは文書の送信リクエストに対して強制されるため、埋め込み側の要件と
文書自身の表明の両方が適用される。[csp-embedded-enforcement]に従い、
応答がすでに要件を満たす許可リストを
表明している場合、その表明がすでに要件を満たし、追加項目が不要であるため、要件は
付加されない。
注記: 未解決の要件を
result のポリシーコンテナに格納することで、要件が
子孫へ伝播する。各子孫は、自身の応答に対して、要件(およびその
response-originトークン)を
再解決する。
したがって、フレームは、自身に強制される許可リストが要件より厳格である場合でも、その子に対してポリシーを
強制する義務を負う。ローカル
スキーム(about:srcdoc や data: など)から作成された
Documentでは、
ポリシーコンテナが
埋め込み側から継承されるため、要件もそれとともに継承される。
ブロックの決定は Fetch で行われる。ハンドシェイクに失敗したナビゲーションの応答は、 ネットワークエラーに置き換えられる。子ナビガブルを対象とするナビゲーションリクエスト(request)に対する応答を 取得した後、その応答が、request とナビゲーションの必須接続許可リストを与えて、 Connection Allowlist の埋め込み強制によってブロックされるべきかを 決定した結果がブロック済みである場合、 ユーザーエージェントは ネットワークエラーを返す。
Fenced Frame および、 そのリクエストが埋め込み側の ポリシーコンテナによって管理されないその他のコンテキストは、 この仕組みによって制約できない。そのようなコンテキストは、埋め込み側から 接続許可リストを要求された場合、制約なしで読み込むことを許可せず、 ブロックしなければならない。§ 6.2 埋め込み強制を参照されたい。
この統合は意図的に、 コンテンツ セキュリティポリシー:埋め込み強制 § 2.4 HTML との統合と並行するように設計されている。両者の 仕組みは、保持されるポリシーの種類と「少なくとも同じ程度に厳格」という比較のみが異なる。 理想的には、共有される基盤(ターゲットスナップショットパラメーター/ナビゲーションパラメーター項目、 リクエストヘッダーのフック、およびポリシーコンテナへの適用)は HTML(または共有の 埋め込みポリシー強制仕様)に切り出され、ポリシーの種類をパラメーター化すべきである。2 つの 仕様を単一の仕組みに整合させることは、後続作業として追跡されている。
5.3. DNS プリフェッチ
dns-prefetchリンク型の
リンクされたリソースをフェッチして処理する手順では、
リンク要素のノード文書をオリジンを
解決するに渡す:
dns-prefetchリンク型について、手順 4 を次のように
更新する:
-
ユーザーエージェントは、partitionKey、 url のオリジン 、および el の関連設定オブジェクト を与えて、オリジンを解決するべきである。
5.4. 事前接続
事前接続アルゴリズムでは、リンクオプションの環境を接続を取得するに渡す:
5.5. WebRTC との統合
WebRTC 接続を制約するため、[webrtc]は、候補が管理上禁止されているかどうかを決定する際に、 WebRTC を Connection Allowlists によってブロックすべきか アルゴリズムを呼び出すことができる。
5.6. Service Worker との統合
Service Worker 自身のポリシーコンテナを適用する既定の動作に加えて、
Service Worker は、WindowClient
API を使用してナビゲーションを呼び出す際に、自身の接続許可リストを適用する必要がある。
navigate()
および openWindow(url)
アルゴリズムは、いずれも次のように修正しなければならない:
-
URL を
Connection Allowlists によってブロックすべきかを、url、this の関連設定オブジェクト、およびthis の
関連設定オブジェクトのポリシーコンテナの接続許可リストに対して
実行したとき、ブロック済みを返す場合、
"SecurityError"DOMExceptionで拒否されたプロミスを返す。
navigate()
は、現在の文書をナビゲーションの sourceDocument として渡す。これは多少
見落としのように思われる。議論を参照されたい。
6. セキュリティおよびプライバシーに関する考慮事項
6.1. 同一オリジンコンテキスト
§ 1.1 脅威モデルで説明されている脅威モデルは意図的に限定されており、
開発者は、ここで説明する許可リストメカニズムを自身の防御にどのように重ね合わせるかを
慎重に検討する必要があります。最も重要な点として、このメカニズムはコンテキスト固有であり、
オリジン全体に適用されるものではありません。このため、スクリプトアクセス権を持つ攻撃者が、
制約の弱い同一オリジン
コンテキストを見つけることで、あるコンテキストの許可リストを回避できる可能性が広く残されています。
HTML のポリシーコンテナーとの統合により、
そうした可能性の一部には対処できますが、ほかにも存在する可能性があります。たとえば、攻撃者は
フレームツリーを上にたどって制約の弱い親に到達したり、オープナー関係を維持する
window.open()を介して新しいウィンドウを開いたりできる可能性があります。したがって、文書のオリジンを
(response-originを介して、または
明示的に)許可リストに登録することだけでは、
それ自体で完全な解決策にはなりません。
開発者が、許可リストを適用したコンテキストを通常のオリジンから
sandbox
属性またはコンテンツセキュリティポリシーの
sandbox
ディレクティブによって分離し、このリスクを回避できるシナリオもあります。そのような場合、
同一オリジンとなる文書は存在せず、境界を維持しやすくなります。
開発者は、フレーム化された各文書が自身を制約することに依存する代わりに、§ 4 埋め込み適用で説明されている埋め込み適用メカニズムを使用して、 フレーム化する文書に接続許可リストを 要求することもできます。
6.2. 埋め込み適用
§ 4 埋め込み適用により、埋め込み元はフレーム化された文書に接続 許可リストを要求でき、 issue #1が解決されます。いくつかの 特性により、これが新たな攻撃対象領域になることを防ぎます:
-
必須のオプトイン。 埋め込み元は、同意しないクロスオリジン コンテンツにポリシーを課すことはできません。フレーム化された文書は、要件を 満たす `
Connection-Allowlist` を表明するか、 埋め込み元を指定する `Allow-Connection-Allowlist-From` ヘッダーを返さなければなりません。 オプトインがなく(かつローカルスキームからの配信でもない) 場合、フレームはブロックされます。これは、iframeのcsp属性にオプトインを要求する動機となった懸念を反映しています。 [csp-embedded-enforcement] -
継承時に緩和しないこと。 要件は子孫フレームによって 継承され、 子孫自身の
connectionAllowlist属性は、継承された要件を 満たす場合にのみ 尊重されます。したがって、制約されたサブフレームが、より制約の緩い孫を埋め込むことによって 自身の制約から逃れることはできません。ローカルスキームの 文書についても、継承された許可リストが埋め込み適用によって緩和されることはありません。 -
保守的な受け入れ。 不正な形式で表明された `
Connection-Allowlist` はnullに解析され、オプトインとは見なされません。また、厳格性の比較は、 保守的な構文上の集合所属判定です。したがって、フレーム化された文書が、 実際には満たしていない要件を満たすことはできません。
リクエストが埋め込み元のポリシーコンテナーによって管理されないコンテキスト (たとえばフェンス付きフレーム)は、このメカニズムによって制約できません。そのようなコンテキストに対して 埋め込み元が接続許可リストを要求する場合、制約なしで読み込むことを 許可するのではなく、そのコンテキストをブロックしなければなりません。
6.3. Service Worker
Service Worker は、他の同一オリジンのコンテキストと同様に、許可リストをめぐる事情を複雑にします。 これらは、管理する各文書とは異なる ポリシーコンテナを持つため、 Service Worker の許可リストとは異なる許可リストを持つ文書で開始されたメッセージやリクエストに応答することは 十分にあり得ます。この提案は他のポリシーの設計に従い、 このような機能の違いを許容します。
文書の接続許可リストは、Service Worker がリクエストを傍受する前に適用されることに注意してください。 したがって、リクエストが文書自身の接続許可リストによってブロックされる場合、Service Worker が その文書からのリクエストを目にすることはありません。
ただし、Service Worker は、文書に代わって外部への fetch
リクエストを仲介することにより
(たとえば postMessage(...) を介して)、文書が自身の接続許可リストを回避するのを支援できてしまいます。この
情報流出経路から保護するため、開発者は
Worker スクリプトとともに同等に制限的な許可リストを配信できます。これは、すべての配信スクリプトに
適用するのではなく、Sec-Fetch-Dest リクエストヘッダーが serviceworker である場合に
条件付きで
`Connection-Allowlist`
ヘッダーを送信することで効率的に行えます。
Service Worker の場合、この許可リストは、その Worker が処理する可能性のあるすべての文書の
許可リストのスーパーセットでなければならないことに注意してください。
6.4. Shared Worker
Service Worker と同様に、Shared Worker は独自の ポリシーコンテナを持ち、postMessage(...) を介して文書に
代わって情報流出を仲介できる可能性があります。開発者は同様に、Shared Worker スクリプトとともに制限的な
許可リストを配信できます(Sec-Fetch-Dest リクエストヘッダーが
sharedworker であるかを確認することによって)。
blob: URL から作成された Shared Worker には、特有の回避リスクがあります。data:
URL の Shared Worker は開始元のポリシーコンテナを安全に継承しますが、blob: URL の Shared Worker
には、異なる接続許可リストを持つ複数の文書から接続できます。この
文書間の回避を防ぐため、接続許可リストを使用する開発者には、
blob: URL を除外する worker-src Content Security Policy ディレクティブを
指定することが推奨されます。
6.5. DNS
接続許可リストは、DNS ルックアップを介した情報流出のリスクを軽減することを目的としており、Fetch の
オリジンを解決するアルゴリズムを変更して、DNS リクエストを送信する前に
許可リストを確認します。これは、リクエストを送信する要素や API の使用によって生じる暗黙的な
ルックアップ(img
タグ、fetch()
など)だけでなく、
dns-prefetch のような仕組みによって明示的に引き起こされるルックアップにも
対処します。
とはいえ、許可リストは、特定のエンドポイントが 許容可能かどうかを判断するために URL ベースの照合に依存しています。これは DNS 操作に対する防御ではなく、 リクエストに関与する DNS サーバーを制限するものでもありません(DNS 解決の再帰的な性質によって 複数のサーバーと通信する可能性があることも含みます)。また、CNAME のような構成によって 許可リスト外のドメインに対する追加のルックアップが発生することも制限しません。同様に、許可リストは、 DNS が指し示すサーバーが想定しているサーバーであることを保証できません。
開発者は、認証された 接続に依存することで、DNS ハイジャックやリバインディングのリスクを軽減するべきです。安全なプロトコルだけを許可リストに含めれば、 DNS を制御する攻撃者がトラフィックを任意のエンドポイントへ移すことははるかに困難になります。TLS ハンドシェイクには 該当する名前を持つ証明書の所持が必要になるためです。
許可リストの パターンを、安全なプロトコルを表すものだけに制限するべきでしょうか?それとも 非セキュアオリジンについてはヘッダー自体を断念するべきでしょうか?
6.6. postMessage(...)
この提案はネットワーク接続のみを対象としており、
postMessage(message, options)、
MessageChannel、
BroadcastChannel
などの明示的な通信チャネルを介した通信も
対象になると予想する開発者にとっては意外かもしれません。これらもすべて、
許可リストと有意義に比較できるオリジンベースのモデルに適合するため、このモデルを拡張してこれらも含めることには
意味があるかもしれません。
6.7. リダイレクト
デフォルトでは、接続許可リストはすべてのリダイレクトをブロックします。これは、 オープンリダイレクトやその他のサーバー側リダイレクト機構を介したデータ流出を防ぐことを目的とした保守的な方針です。 文書に許可リストが適用されている場合、リダイレクトを許可することを許可リストが明示的に指定していない限り、 リダイレクトが発生するすべてのリクエストはブロックされます。
redirects パラメーターを使用すると、
開発者は
この動作を制御できます。
block(デフォルト)に設定した場合、
リダイレクトチェーンの長さが 1 を超えるすべての
リクエストがブロックされます。
allow に設定した場合、許可リストは
最初のリクエストに対してのみ適用されます。最初のリクエストが許可リストに一致すれば、その後のすべてのリダイレクトは、
その場所にかかわらず許可されます。このモードでは、データセキュリティの責任が
サーバー側へ移ります。リクエストがクライアントから送出されることを許可された後は、サーバーが、
ユーザーのデータを信頼されていない場所へリダイレクトしないようにする責任を負います。
この方式は、アプリケーションごとに異なるセキュリティ要件があることを考慮しています。 高度に機密性の高いアプリケーションはすべてのリダイレクトをブロックすることを選択でき、それ以外のアプリケーションは、 信頼されたエンドポイントがリダイレクトを正しく処理することに依存できます。
Connection-Allowlist: ("https://api.example")
https://api.example/data へのリクエストが 302 Found リダイレクトを返して
https://api.example/new-data に移動する場合、リダイレクトはデフォルトでブロックされるため、
ブロックされます。
代わりにヘッダーが次のような場合:
Connection-Allowlist: ("https://api.example");redirects=allow
https://api.example/data への同じリクエストは 許可され、その後の
https://api.example/new-data(または https://attacker.com/ でさえ)へのリダイレクトも
許可されます。
最後に、前方互換性のため、不明なトークンは allow として扱われます:
Connection-Allowlist: ("https://api.example");redirects=some-future-policy
この場合、redirects パラメーターは存在しますが、その値
some-future-policy は不明です。
ユーザーエージェントはこれを allow として扱い、リダイレクトは 許可されます。
これにより、
既存のサイトを壊すことなく、将来追加の動作を導入できる可能性が確保されます。
6.8. WebRTC
デフォルトでは、接続許可リストはすべての WebRTC 接続をブロックします。これは、 URL パターンだけでは制約することが困難な WebRTC 固有のネットワーク 特性を介したデータ流出のリスクを軽減することを意図した保守的な方針です。
webrtc パラメーターを使用すると、開発者は
この動作を
制御できます。
block(デフォルト)に設定した場合、
WebRTC 接続を
確立しようとするすべての試みがブロックされます。
allow に設定した場合、WebRTC 接続は
許可されます。
Connection-Allowlist: ("https://api.example")
WebRTC はデフォルトでブロックされるため、WebRTC 接続を確立しようとするすべての試みは ブロックされます。
代わりにヘッダーが次のような場合:
Connection-Allowlist: ("https://api.example"); webrtc=allow
WebRTC 接続は 許可されます。
7. 実装上の考慮事項
7.1. WebSocket
WebSocket 接続は、ws または wss スキームを指定するパターンではなく、http および https
パターンの対象となることを覚えておくとよい。WebSocket 接続を確立するとき、手順 1 では、
WebSocket 固有のこれらのスキームを、それぞれ http および https に書き換える。これは、
「ws://socket.example」のようなパターンを含む許可リストは意図した効果を持たないことを
意味する。そのパターンがリソースリクエストに一致することは決してないためである。