External Resource Integrity
概要
本文書で定義される External Resource Integrity は画像や動画などの外部リソースファイルの完全性を保証するための Content Attestation (CA) のプロパティです。 URL が参照するリソースの完全性を保証できる一方で、扱える URL はユーザーエージェントに依らず同じバイト列をレスポンスとして返却するものに限られます。
この External Resource Integrity について実証実験の参加企業の方々からフィードバックをいただく予定です。また関連する仕様のアップデートの状況を見ながらよりよい方法を将来追加する可能性があります。
参考: 画像加工を伴う CDN 利用時の検証可能化方法の検討
範囲
- 動画ファイルについては Adaptive Bitrate Streaming で配信される動画は扱いません。単一の動画ファイルとして配信される動画のみ扱います。
- background-image CSS プロパティや content CSS プロパティといった CSS で取得表示されるリソースは本文書の範囲外です。
- コンテンツネゴシエーションによる動的なリソースは本文書の範囲外です。
用語
本文書に説明のない用語については、用語を参照してください。
- Content Attestation (CA)
External Resource Integrity の形式
JSON オブジェクトでなければなりません。 External Resource Integrity の具体例を次に示します。
{
"type": "ExternalResourceTargetIntegrity",
"cssSelector": "#hero-image",
"integrity": "sha256-OYP9B9EPFBi1vs0dUqOhSbHmtP+ZSTsUv2/OjSzWK0w="
}
以下のプロパティが定義されます:
| Name | Type | Description |
|---|---|---|
type | string | REQUIRED. 必ず ExternalResourceTargetIntegrity でなければなりません (MUST)。 |
integrity | string | REQUIRED. sriString データ型 でなければなりません (MUST)。使用可能なハッシュ関数についてはハッシュアルゴリズムに準拠してください (MUST)。具体例: sha256-4HLmAAYVRClrk+eCIrI1Rlf5/IKK0+wGoYjRs9vzl7U= |
cssSelector | string | OPTIONAL. 必ず CSS セレクター (Selectors Level 3) でなければなりません (MUST)。このプロパティがある場合、対象となる HTML 要素の特定に integrity 属性ではなく CSS セレクターを使用します。具体例: #hero-image |
CA 発行者は、ページの動的な変化によらず cssSelector がマッチする要素が変わらないように cssSelector を指定してください (RECOMMENDED)。たとえば、cssSelector に img などのタグ名だけを指定するのではなく、 #hero-image, img.rareClassName のようにより詳細な CSS セレクターを指定してください。対象要素を安定的に一意に特定するような CSS セレクターがないときには、ページを更新して、対象要素に id 属性を指定するなどして特定しやすいようなページ設計をしてください (RECOMMENDED)。
設定方法
検証対象の HTML 要素は、次のいずれかの方法で特定できるようにします。
cssSelectorプロパティを使用する場合: 検証対象リソースを参照する HTML 要素リストにマッチする CSS セレクターをcssSelectorプロパティに指定します。cssSelectorプロパティを使用しない場合:integrityプロパティと同じ値を HTML 要素のintegrity属性に指定します。
例
cssSelector プロパティで要素を特定する場合
source 要素と img 要素を cssSelector プロパティで参照する場合の具体例を次に示します。
External Resource Integrity:
[
{
"type": "ExternalResourceTargetIntegrity",
"cssSelector": "#hero-image-source",
"integrity": "sha256-4HLmAAYVRClrk+eCIrI1Rlf5/IKK0+wGoYjRs9vzl7U="
},
{
"type": "ExternalResourceTargetIntegrity",
"cssSelector": "#hero-image",
"integrity": "sha256-t7WZSGxDdqGvGg/FLw6wk9KFQy5StT1MquCf/htwjBo= sha256-4HLmAAYVRClrk+eCIrI1Rlf5/IKK0+wGoYjRs9vzl7U="
}
]
このとき Web ページの HTML の source 要素と img 要素に、次のように CSS セレクターがマッチするようにします。
<picture>
<source
id="hero-image-source"
srcset="image.jpg"
media="(min-width: 400px)"
/>
<img id="hero-image" src="https://cdn.example.com/image.jpg" />
</picture>
video 要素を cssSelector プロパティで参照する場合の具体例を次に示します。
External Resource Integrity:
[
{
"type": "ExternalResourceTargetIntegrity",
"cssSelector": "#product-video",
"integrity": "sha256-OYP9B9EPFBi1vs0dUqOhSbHmtP+ZSTsUv2/OjSzWK0w= sha256-zc3KMRPJkbv6p7sOq5Di/CNe+4XyqBBuiKjzP3A3NP0="
},
{
"type": "ExternalResourceTargetIntegrity",
"cssSelector": "#product-video-mp4",
"integrity": "sha256-OYP9B9EPFBi1vs0dUqOhSbHmtP+ZSTsUv2/OjSzWK0w="
},
{
"type": "ExternalResourceTargetIntegrity",
"cssSelector": "#product-video-webm",
"integrity": "sha256-zc3KMRPJkbv6p7sOq5Di/CNe+4XyqBBuiKjzP3A3NP0="
}
]
このとき Web ページの HTML の video 要素と source 要素に、次のように CSS セレクターがマッチするようにします。
<video id="product-video" poster="https://cdn.example.com/poster.jpg">
<source
id="product-video-mp4"
src="https://cdn.example.com/video.mp4"
type="video/mp4"
/>
<source
id="product-video-webm"
src="https://cdn.example.com/video.webm"
type="video/webm"
/>
</video>
同じリソースを参照する複数の要素をひとつの External Resource Integrity で参照する場合の具体例を次に示します。
External Resource Integrity:
{
"type": "ExternalResourceTargetIntegrity",
"cssSelector": ".site-logo",
"integrity": "sha256-OYP9B9EPFBi1vs0dUqOhSbHmtP+ZSTsUv2/OjSzWK0w="
}
このとき Web ページの HTML の img 要素に、次のように CSS セレクターがマッチするようにします。.site-logo は 2 つの img 要素にマッチするため、そのどちらも integrity プロパティと一致しなければなりません (MUST)。
<header>
<img class="site-logo" src="https://cdn.example.com/logo.png" />
</header>
<footer>
<img class="site-logo" src="https://cdn.example.com/logo.png" />
</footer>
integrity 属性で要素を特定する場合
source 要素と img 要素を External Resource Integrity から参照する場合の具体例を次に示します。
External Resource Integrity:
[
{
"type": "ExternalResourceTargetIntegrity",
"integrity": "sha256-4HLmAAYVRClrk+eCIrI1Rlf5/IKK0+wGoYjRs9vzl7U="
},
{
"type": "ExternalResourceTargetIntegrity",
"integrity": "sha256-t7WZSGxDdqGvGg/FLw6wk9KFQy5StT1MquCf/htwjBo= sha256-4HLmAAYVRClrk+eCIrI1Rlf5/IKK0+wGoYjRs9vzl7U="
}
]
このとき Web ページの HTML の source 要素と img 要素に次のように integrity 属性を付与します。
<picture>
<source
srcset="image.jpg"
media="(min-width: 400px)"
integrity="sha256-4HLmAAYVRClrk+eCIrI1Rlf5/IKK0+wGoYjRs9vzl7U="
/>
<img
src="https://cdn.example.com/image.jpg"
integrity="sha256-t7WZSGxDdqGvGg/FLw6wk9KFQy5StT1MquCf/htwjBo= sha256-4HLmAAYVRClrk+eCIrI1Rlf5/IKK0+wGoYjRs9vzl7U="
/>
</picture>
video 要素を External Resource Integrity から参照する場合の具体例を次に示します。
External Resource Integrity:
[
{
"type": "ExternalResourceTargetIntegrity",
"integrity": "sha256-OYP9B9EPFBi1vs0dUqOhSbHmtP+ZSTsUv2/OjSzWK0w= sha256-zc3KMRPJkbv6p7sOq5Di/CNe+4XyqBBuiKjzP3A3NP0="
},
{
"type": "ExternalResourceTargetIntegrity",
"integrity": "sha256-zc3KMRPJkbv6p7sOq5Di/CNe+4XyqBBuiKjzP3A3NP0="
}
]
このとき Web ページの HTML の source 要素と video 要素に次のように integrity 属性を付与します。
<video
integrity="sha256-OYP9B9EPFBi1vs0dUqOhSbHmtP+ZSTsUv2/OjSzWK0w= sha256-zc3KMRPJkbv6p7sOq5Di/CNe+4XyqBBuiKjzP3A3NP0="
poster="https://cdn.example.com/poster.jpg"
>
<source
src="https://cdn.example.com/video.mp4"
integrity="sha256-OYP9B9EPFBi1vs0dUqOhSbHmtP+ZSTsUv2/OjSzWK0w="
type="video/mp4"
/>
<source
src="https://cdn.example.com/video.webm"
integrity="sha256-zc3KMRPJkbv6p7sOq5Di/CNe+4XyqBBuiKjzP3A3NP0="
type="video/webm"
/>
</video>
注意事項
video 要素を参照する場合、src 属性に指定された外部リソースが検証され、poster 属性に指定された外部リソースは検証されません。poster 属性に指定された外部リソースを検証可能にするための仕様は検討中です。
a 要素の href 属性で指定された外部リソースを検証可能にするための仕様は検討中です。現在の検証プロセスでは src 属性または currentSrc プロパティを使用したリソース取得のみが定義されています。詳しくは GitHub Issue #127 をご確認ください。
SRI セクション 5.3 にあるように、攻撃者が既知あるいは事前に計算したハッシュ値により、同一オリジンポリシーに違反してクロスオリジンリソースの内容を推測することを防ぐために、SRI 検証結果をクロスオリジンリソースの読み込み可否に使用する場合には、事前にCORS プロトコルを使用してクロスオリジンリソースがリクエスト元と明示的に共有されていることを確認してください。
検証プロセス
- External Resource Integrity に対応する HTML 要素を検索します。
cssSelectorプロパティがある場合、cssSelectorプロパティの CSS セレクターで指定した要素を検索します。対象の要素は、そのページのdocumentのルート要素 (例えば、 HTML 文書の場合は<html>要素) から、querySelectorAll()メソッドを使用して検索します。cssSelectorプロパティの構文エラーがある場合、検証失敗として扱うことがあります。(例:DOMExceptionSyntaxError)
cssSelectorプロパティがない場合、integrityプロパティと同じ値をintegrity属性に含む要素を検索します。- 要素が1つも見つからない場合、検証失敗として扱うことがあります。
- 手順1に該当したすべての要素に対応するリソースを取得します。
- リソースは、要素の種類に応じた属性またはプロパティの URL から取得します。
- img 要素:
HTMLImageElement.currentSrcプロパティ - video 要素または audio 要素:
HTMLMediaElement.currentSrcプロパティ - その他の要素:
src属性
- img 要素:
- ネットワークエラーが発生した場合、検証失敗として扱うことがあります。(例:
TypeErrorFailed to fetch.など)
- リソースは、要素の種類に応じた属性またはプロパティの URL から取得します。
- 手順2で取得したそれぞれのリソースと
integrityプロパティを SRI セクション 3.3.5 に規定されている方法で検証します。- サポートしていないハッシュアルゴリズムの場合、検証失敗として扱うことがあります。
要素位置特定方法
cssSelector プロパティの有無に応じて次のように要素を特定します。
cssSelectorプロパティがある場合:cssSelectorプロパティの CSS セレクターで指定した要素を検索します。cssSelectorプロパティがない場合:integrityプロパティと同じ値を HTML 要素のintegrity属性に対し完全一致で検索します。
cssSelector プロパティがなく次の場合には、integrity プロパティと HTML 要素の integrity 属性値の両者が同じ値になるように注意する必要があります。
integrityプロパティの値が 2 件以上の SRI ハッシュである- HTML 要素の
integrity属性値に読みやすさのために空白文字または改行文字を使用している
参考文献
- W3C Subresource Integrity
- webappsec-subresource-integrity/signature-based-restrictions-explainer.markdown at main · w3c/webappsec-subresource-integrity
- Content Security Policy Level 3
- Apply subresource integrity to
<img>tags · Issue #113 · w3c/webappsec-subresource-integrity - integrity for downloads · Issue #68 · w3c/webappsec-subresource-integrity
- SRI: Integrity enforcement on downloads · Issue #497 · w3c/webappsec
- [SRI] Support signatures/asymm key · Issue #449 · w3c/webappsec
- Consideration: Allow integrity-check based on signature instead of actual hash · Issue #85 · w3c/webappsec-subresource-integrity