Reporting API を使用して、セキュリティ違反や非推奨の API 呼び出しなどをモニタリングします。
一部のエラーは、本番環境でのみ発生します。実際のユーザー、実際のネットワーク、実際のデバイスによってゲームが変化するため、ローカルや開発中は問題は発生しません。Reporting API は、セキュリティ違反や、サイト全体で非推奨またはまもなく非推奨になる API 呼び出しなどのエラーを検出し、指定したエンドポイントに送信します。
HTTP ヘッダーを介してモニタリングする対象を宣言でき、ブラウザによって操作されます。
Reporting API を設定すると、ユーザーがこの種のエラーに遭遇したときは把握でき、修正する安心感が得られます。
この記事では、この API の機能と使用方法について説明します。それでは詳しく見ていきましょう。
デモとコード
Reporting API は、Chrome 96 以降(2021 年 10 月時点では Chrome ベータ版または Canary)で利用できます。
概要
サイト site.example
に Content-Security-Policy と Document-Policy があるとします。これらの機能の詳細については、それでも、この例を理解できます。
これらのポリシーに違反したときに知るためだけでなく、コードベースで使用されている非推奨の API やまもなく非推奨になる API を監視するために、サイトをモニタリングすることにしました。
これを行うには、Reporting-Endpoints
ヘッダーを構成し、必要に応じてポリシーの report-to
ディレクティブを使用してこれらのエンドポイント名をマッピングします。
Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"
# Content-Security-Policy violations and Document-Policy violations
# will be sent to main-endpoint
Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint;
Document-Policy: document-write=?0; report-to=main-endpoint;
# Deprecation reports don't need an explicit endpoint because
# these reports are always sent to the `default` endpoint
予期しないことが起こり、一部のユーザーがこれらのポリシーに違反しています。
違反の例
index.html
<script src="script.js"></script>
<!-- CSP VIOLATION: Try to load a script that's forbidden as per the Content-Security-Policy -->
<script src="https://example.com/script.js"></script>
script.js
、index.html
が読み込みました
// DOCUMENT-POLICY VIOLATION: Attempt to use document.write despite the document policy
try {
document.write('<h1>hi</h1>');
} catch (e) {
console.log(e);
}
// DEPRECATION: Call a deprecated API
const webkitStorageInfo = window.webkitStorageInfo;
ブラウザは、CSP 違反レポート、ドキュメント ポリシー違反レポート、非推奨レポートを生成し、これらの問題をキャプチャします。
ブラウザは、この違反タイプ用に構成されたエンドポイントに、短い遅延(最大 1 分)でレポートを送信します。レポートは、ブラウザ自体によってアウトオブバンドで送信されます(サーバーやサイトから送信されることはありません)。
エンドポイントはこれらのレポートを受信します。
これらのエンドポイントのレポートにアクセスして、問題をモニタリングできるようになりました。これで、ユーザーに影響している問題のトラブルシューティングを開始できます。
サンプル レポート
{
"age": 2,
"body": {
"blockedURL": "https://site2.example/script.js",
"disposition": "enforce",
"documentURL": "https://site.example",
"effectiveDirective": "script-src-elem",
"originalPolicy": "script-src 'self'; object-src 'none'; report-to main-endpoint;",
"referrer": "https://site.example",
"sample": "",
"statusCode": 200
},
"type": "csp-violation",
"url": "https://site.example",
"user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
}
ユースケースとレポートの種類
Reporting API は、サイト全体で発生するさまざまな種類の警告や問題をモニタリングできるように構成できます。
レポートの種類 | レポートが生成される状況の例 |
---|---|
CSP 違反(レベル 3 のみ) | いずれかのページに Content-Security-Policy (CSP)を設定していますが、CSP で許可されていないスクリプトを読み込もうとしています。 |
COOP 違反 | ページに Cross-Origin-Opener-Policy を設定しましたが、クロスオリジン ウィンドウがドキュメントを直接操作しようとしています。 |
COEP 違反 | ページには Cross-Origin-Embedder-Policy が設定されていますが、ドキュメントにはクロスオリジン ドキュメントによる読み込みが有効になっていないクロスオリジン iframe が含まれています。 |
ドキュメント ポリシー違反 | ページに document.write の使用を禁止するドキュメント ポリシーがありますが、スクリプトが document.write を呼び出そうとしています。 |
権限に関するポリシー違反 | ページには、マイクの使用を禁止する権限ポリシーと、音声入力をリクエストするスクリプトがあります。 |
非推奨に関する警告 | ページで、非推奨または非推奨になる API が使用されています。この API は、直接またはトップレベルのサードパーティ スクリプトを介して呼び出されます。 |
介入 | ページが、セキュリティ、パフォーマンス、ユーザー エクスペリエンスの理由でブラウザが許可しない操作をしようとしています。Chrome の例: ページで速度が遅いネットワークで document.write が使用されているか、ユーザーがまだ操作していないクロスオリジン フレームで navigator.vibrate が呼び出されています。 |
衝突事故 | サイトを開いているときにブラウザがクラッシュする。 |
レポート
レポートの表示例
ブラウザは、設定したエンドポイントにレポートを送信します。次のようなリクエストが送信されます。
POST
Content-Type: application/reports+json
これらのリクエストのペイロードはレポートのリストです。
レポートのリスト例
[
{
"age": 420,
"body": {
"columnNumber": 12,
"disposition": "enforce",
"lineNumber": 11,
"message": "Document policy violation: document-write is not allowed in this document.",
"policyId": "document-write",
"sourceFile": "https://site.example/script.js"
},
"type": "document-policy-violation",
"url": "https://site.example/",
"user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
},
{
"age": 510,
"body": {
"blockedURL": "https://site.example/img.jpg",
"destination": "image",
"disposition": "enforce",
"type": "corp"
},
"type": "coep",
"url": "https://dummy.example/",
"user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
}
]
各レポートで確認できるデータは次のとおりです。
フィールド | 説明 |
---|---|
age |
レポートのタイムスタンプから現在の時刻までのミリ秒数。 |
body |
JSON 文字列としてシリアル化された実際のレポートデータ。レポートの body に含まれるフィールドは、レポートの type によって決まります。⚠️ レポートの種類によって本文が異なります。
各レポートタイプの正確な本文については、レポート エンドポイントのデモ を確認し、手順に沿ってサンプル レポートを生成します。 |
type |
レポートのタイプ(csp-violation 、coep など)。 |
url |
レポートが生成されたドキュメントまたはワーカーのアドレス。ユーザー名、パスワード、フラグメントなどの機密データは、この URL から削除されます。 |
user_agent |
レポートが生成されたリクエストの User-Agent ヘッダー。 |
クルデンシャル レポート
レポートを生成するページと同じオリジンを持つレポート エンドポイントは、レポートを含むリクエストで認証情報(Cookie)を受け取ります。
認証情報は、特定のユーザーのアカウントでエラーが常に発生しているかどうか、他のページで行われた特定の操作の順序がこのページで報告をトリガーしているかどうかなど、報告に関する追加のコンテキストを提供できます。
ブラウザはいつ、どのようにレポートを送信しますか?
レポートはサイトからアウトバンドで配信される: レポートが設定されたエンドポイントに送信されるタイミングはブラウザによって制御されます。また、ブラウザがレポートを送信するタイミングを制御することもできません。ブラウザは、適切なタイミングでレポートをキャプチャし、キューに入れて自動的に送信します。
つまり、Reporting API を使用する場合、パフォーマンスに関する懸念はほとんどありません。
レポートをバッチで送信する可能性を高めるために、レポートは遅延して送信されます(最大 1 分)。これにより、ユーザーのネットワーク接続に配慮して帯域幅を節約できます。これはモバイルでは特に重要です。ブラウザが優先度の高い処理で忙しい場合や、ユーザーが低速または輻輳しているネットワークを使用している場合、配信が遅れることもあります。
サードパーティとファースト パーティに関する問題
ページで発生した違反や非推奨化が原因で生成されたレポートは、設定したエンドポイントに送信されます。これには、ページで実行されているサードパーティ スクリプトによる違反も含まれます。
ページに埋め込まれたクロスオリジン iframe で発生した違反やサポートの終了は、エンドポイントには報告されません(少なくともデフォルトでは報告されません)。iframe は独自のレポートを設定でき、サイト(ファーストパーティ)のレポート サービスにレポートすることもできますが、これはフレーム設定されたサイト次第です。また、ほとんどのレポートは、ページのポリシーに違反している場合にのみ生成され、ページのポリシーと iframe のポリシーが異なることにも注意してください。
非推奨の例
ブラウザ サポート
次の表に、Reporting API v1(Reporting-Endpoints
ヘッダー)のブラウザ サポートの概要を示します。Reporting API v0(Report-To
ヘッダー)のブラウザ サポートは、1 つのレポート タイプを除き同じです。新しい Reporting API では、ネットワーク エラー ロギングはサポートされていません。詳しくは、移行ガイドをご覧ください。
レポートの種類 | Chrome | Chrome iOS | Safari | Firefox | Edge |
---|---|---|---|---|---|
CSP 違反(レベル 3 のみ)* | ✔ はい | ✔ はい | ✔ はい | ✘ いいえ | ✔ はい |
ネットワーク エラーのロギング | ✘ いいえ | ✘ いいえ | ✘ いいえ | ✘ いいえ | ✘ いいえ |
COOP/COEP 違反 | ✔ はい | ✘ いいえ | ✔ はい | ✘ いいえ | ✔ はい |
その他のすべてのタイプ: ドキュメント ポリシー違反、非推奨、介入、クラッシュ | ✔ はい | ✘ いいえ | ✘ いいえ | ✘ いいえ | ✔ はい |
次の表は、新しい Reporting-Endpoints
ヘッダーを使用した report-to
のサポートをまとめたものです。Reporting-Endpoints
への移行をお考えの場合は、CSP レポートの移行に関するヒントをご覧ください。
Reporting API の使用
レポートの送信先を決定する
次のどちらかの方法でお問い合わせください。
- 既存のレポート コレクタ サービスにレポートを送信します。
- 自分で構築して運用するレポート コレクタにレポートを送信します。
オプション 1: 既存のレポート コレクタ サービスを使用する
レポート収集サービスの例を次に示します。
他に解決策をご存じの場合は、問題を報告してご連絡ください。この投稿を更新いたします。
レポート コレクタを選択する際は、料金のほかに次の点も考慮してください。 🧐?
- このコレクタはすべてのレポートタイプをサポートしていますか?たとえば、すべてのレポート エンドポイント ソリューションが COOP/COEP レポートをサポートしているわけではありません。
- サードパーティのレポート収集ツールとアプリの URL を共有することに抵抗はありませんか?ブラウザがこれらの URL から機密情報を削除しても、機密情報が漏洩する可能性があります。これがアプリケーションにとってリスクが高すぎると思われる場合は、独自のレポート エンドポイントを運用してください。
オプション 2: 独自のレポート コレクタを構築して運用する
レポートを受け取る独自のサーバーを構築するのは簡単ではありません。始めに、軽量なボイラープレートをフォークします。Express で構築されており、レポートを受信して表示できます。
ボイラープレート レポート コレクタにアクセスします。
[Remix to Edit] をクリックして、プロジェクトを編集可能にします。
これでクローンができました。目的に合わせてカスタマイズできます。
ボイラープレートを使用しておらず、独自のサーバーをゼロから構築している場合:
Content-Type
がapplication/reports+json
のPOST
リクエストをチェックし、ブラウザからエンドポイントに送信されたレポート リクエストを認識します。- エンドポイントがサイトのオリジンと異なる場合は、CORS プリフライト リクエストをサポートしていることを確認します。
オプション 3: オプション 1 と 2 を組み合わせる
特定の種類のレポートの処理は特定のプロバイダに任せ、他のプロバイダは自社ソリューションで処理できます。
この場合は、次のように複数のエンドポイントを設定します。
Reporting-Endpoints: endpoint-1="https://reports-collector.example", endpoint-2="https://my-custom-endpoint.example"
Reporting-Endpoints
ヘッダーを構成する
Reporting-Endpoints
レスポンス ヘッダーを設定します。値は、カンマ区切りのキーバリュー ペアの 1 つまたは一連のペアである必要があります。
Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"
以前の Reporting API から新しい Reporting API に移行する場合は、Reporting-Endpoints
と Report-To
の両方を設定することをおすすめします。詳しくは、移行ガイドをご覧ください。特に、report-uri
ディレクティブのみを使用して Content-Security-Policy
違反のレポートを使用している場合は、CSP レポートの移行手順を確認してください。
Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"
Report-To: ...
キー(エンドポイント名)
各キーは、main-endpoint
や endpoint-1
など、任意の名前にできます。レポートタイプごとに異なる名前付きエンドポイントを設定できます(例: my-coop-endpoint
、my-csp-endpoint
)。これにより、レポートの種類に応じて異なるエンドポイントに転送できます。
介入、非推奨、クラッシュの各レポートを受信する場合は、default
という名前のエンドポイントを設定します。
Reporting-Endpoints
ヘッダーで default
エンドポイントが定義されていない場合、このタイプのレポートは送信されません(生成はされます)。
値(URL)
各値は、レポートを送信する任意の URL です。ここで設定する URL は、ステップ 1 で決定した内容によって異なります。
エンドポイント URL:
- スラッシュ(
/
)で始まる必要があります。相対パスはサポートされていません。 - クロスオリジンにすることもできますが、その場合は認証情報がレポートとともに送信されません。
例
Reporting-Endpoints: my-coop-endpoint="https://reports.example/coop", my-csp-endpoint="https://reports.example/csp", default="https://reports.example/default"
これにより、適切なポリシーで各名前付きエンドポイントを使用することも、すべてのポリシーで単一のエンドポイントを使用することもできます。
ヘッダーはどこに設定すればよいですか?
この投稿で説明する新しい Reporting API では、レポートのスコープはドキュメントに限定されます。つまり、1 つのオリジンに対して、site.example/page1
や site.example/page2
などの異なるドキュメントが異なるエンドポイントにレポートを送信できます。
サイトの任意のページで発生した違反や非推奨に関するレポートを受け取るには、すべてのレスポンスでヘッダーをミドルウェアとして設定します。
Express の例を次に示します。
const REPORTING_ENDPOINT_BASE = 'https://report.example';
const REPORTING_ENDPOINT_MAIN = `${REPORTING_ENDPOINT_BASE}/main`;
const REPORTING_ENDPOINT_DEFAULT = `${REPORTING_ENDPOINT_BASE}/default`;
app.use(function (request, response, next) {
// Set up the Reporting API
response.set(
'Reporting-Endpoints',
`main-endpoint="${REPORTING_ENDPOINT_MAIN}", default="${REPORTING_ENDPOINT_DEFAULT}"`,
);
next();
});
ポリシーを編集する
Reporting-Endpoints
ヘッダーの構成が完了したので、違反レポートを受信する各ポリシー ヘッダーに report-to
ディレクティブを追加します。report-to
の値は、構成した名前付きエンドポイントのいずれかにする必要があります。
複数のポリシーに複数のエンドポイントを使用することも、ポリシー間で異なるエンドポイントを使用することもできます。
report-to
は、非推奨、介入、クラッシュの報告には必要ありません。これらのレポートはポリシーに関連付けられていません。default
エンドポイントが設定されている限り生成され、この default
エンドポイントに送信されます。
例
# Content-Security-Policy violations and Document-Policy violations
# will be sent to main-endpoint
Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint;
Document-Policy: document-write=?0;report-to=main-endpoint;
# Deprecation reports don't need an explicit endpoint because
# these reports are always sent to the default endpoint
コード例
これらすべてをコンテキストで確認するには、Express を使用してこの記事で説明したすべての要素をまとめた Node サーバーのサンプルを以下に示します。いくつかの異なるレポートタイプのレポートを構成し、結果を表示する方法を示します。
レポート設定をデバッグする
意図的にレポートを生成する
Reporting API を設定する際は、レポートが想定どおりに生成され、送信されるかどうかを確認するために、ポリシーを意図的に違反する必要がある場合があります。ポリシーに違反し、あらゆる種類のレポートを生成するその他の不正行為を行うサンプルコードについては、デモをご覧ください。
時間の節約
レポートは遅れて送信されることもありますが、デバッグ時には約 1 分かかります。😴? 幸い、Chrome でデバッグする場合は、--short-reporting-delay
フラグを使用して、レポートが生成された直後にレポートを受け取ることができます。
ターミナルで次のコマンドを実行して、このフラグをオンにします。
YOUR_PATH/TO/EXECUTABLE/Chrome --short-reporting-delay
DevTools を使用する
Chrome では、DevTools を使用して、送信済みまたは送信予定のレポートを確認できます。
2021 年 10 月の時点で、この機能は試験運用版です。使用方法は次のとおりです。
- Chrome バージョン 96 以降を使用している(ブラウザで
chrome://version
と入力して確認) - Chrome のアドレスバーに
chrome://flags/#enable-experimental-web-platform-features
と入力するか、貼り付けます。 - [有効] をクリックします。
- ブラウザを再起動する。
- Chrome DevTools を開きます。
- Chrome DevTools で設定を開きます。[テスト] で、[アプリケーション パネルの Reporting API パネルを有効にする] をクリックします。
- DevTools を再読み込みします。
- ページを再読み込みします。DevTools が開いているページで生成されたレポートは、Chrome DevTools の [Application] パネルの [Reporting API] に表示されます。
レポートのステータス
[ステータス] 列には、レポートが正常に送信されたかどうかが表示されます。
ステータス | 説明 |
---|---|
Success |
ブラウザがレポートを送信し、エンドポイントが成功コード(200 または別の成功レスポンス コード 2xx )で応答しました。 |
Pending |
現在、ブラウザはレポートの送信を試行しています。 |
Queued |
レポートは生成されていますが、ブラウザは現在、レポートの送信を試行していません。レポートは、次の 2 つのケースのいずれかで Queued として表示されます。
|
MarkedForRemoval |
しばらく再試行した後(Queued )、ブラウザはレポートの送信を停止し、まもなく送信するレポートのリストから削除します。 |
レポートは、送信が成功したかどうかにかかわらず、しばらくすると削除されます。
トラブルシューティング
レポートが生成されない、またはエンドポイントに想定どおりに送信されない。この問題を解決するためのヒントをいくつかご紹介します。
レポートが生成されない
DevTools に表示されるレポートは正しく生成されています。想定どおりのレポートがこのリストに表示されない場合:
- ポリシーで
report-to
を確認します。これが正しく構成されていない場合、レポートは生成されません。これを修正するには、ポリシーの編集に移動します。この問題をトラブルシューティングするもう一つの方法は、Chrome の DevTools コンソールを確認することです。想定した違反に関するエラーがコンソールにポップアップ表示された場合は、ポリシーが正しく構成されている可能性があります。 - このリストには、DevTools が開いているドキュメントに対して生成されたレポートのみが表示されます。たとえば、サイト
site1.example
にポリシーに違反する iframesite2.example
が埋め込まれ、レポートが生成された場合、このレポートは、iframe を独自のウィンドウで開き、そのウィンドウの DevTools を開いた場合にのみ DevTools に表示されます。
レポートは生成されるが、送信されない、または受信されない
DevTools にレポートが表示されているのに、エンドポイントがレポートを受信しない場合はどうすればよいですか?
- 短い遅延を使用するようにしてください。レポートがまだ送信されていないことが原因で、レポートが表示されないこともあります。
Reporting-Endpoints
ヘッダーの構成を確認します。問題がある場合、正しく生成されたレポートは送信されません。この場合、DevTools のレポートのステータスはQueued
のままになります(Pending
にジャンプし、配信が試行されるとすぐにQueued
に戻ることがあります)。次のようなよくあるミスが原因で発生することがあります。エンドポイントは使用されていますが、構成されていません。例:
Document-Policy: document-write=?0;report-to=endpoint-1; Reporting-Endpoints: default="https://reports.example/default"
default
エンドポイントがありません。非推奨レポートや介入レポートなど、一部のレポートタイプはdefault
という名前のエンドポイントにのみ送信されます。詳しくは、Reporting-Endpoints ヘッダーを構成するをご覧ください。引用符の欠落など、ポリシー ヘッダーの構文に問題がないか確認します。詳細を表示
エンドポイントが受信リクエストを処理できることを確認します。
エンドポイントが CORS プリフライト リクエストをサポートしていることを確認します。有効になっていない場合、レポートを受信できません。
エンドポイントの動作をテストします。そのためには、レポートを手動で生成するのではなく、ブラウザが送信するリクエストに類似するリクエストをエンドポイントに送信して、ブラウザをエミュレートします。以下のコマンドを実行します。
curl --header "Content-Type: application/reports+json" \ --request POST \ --data '[{"age":420,"body":{"columnNumber":12,"disposition":"enforce","lineNumber":11,"message":"Document policy violation: document-write is not allowed in this document.","policyId":"document-write","sourceFile":"https://dummy.example/script.js"},"type":"document-policy-violation","url":"https://dummy.example/","user_agent":"xxx"},{"age":510,"body":{"blockedURL":"https://dummy.example/img.jpg","destination":"image","disposition":"enforce","type":"corp"},"type":"coep","url":"https://dummy.example/","user_agent":"xxx"}]' \ YOUR_ENDPOINT
エンドポイントは成功コード(
200
または別の成功レスポンス コード2xx
)で応答する必要があります。応答しない場合は、構成に問題があります。
関連するレポート作成メカニズム
レポート専用
-Report-Only
ポリシー ヘッダーと Reporting-Endpoints
は連携して動作します。
Reporting-Endpoints
で構成され、Content-Security-Policy
、Cross-Origin-Embedder-Policy
、Cross-Origin-Opener-Policy
の report-to
フィールドで指定されたエンドポイントは、これらのポリシーに違反するとレポートを受け取ります。
Reporting-Endpoints
で構成されたエンドポイントは、Content-Security-Policy-Report-Only
、Cross-Origin-Embedder-Policy-Report-Only
、Cross-Origin-Opener-Policy-Report-Only
の report-to
フィールドで指定できます。これらのポリシーに違反があった場合には、報告者に報告されます。
どちらの場合もレポートは送信されますが、-Report-Only
ヘッダーではポリシーが適用されません。何も破損したり、実際にブロックされたりすることはありませんが、破損またはブロックされた可能性のある内容のレポートが届きます。
ReportingObserver
ReportingObserver
JavaScript API を使用すると、クライアントサイドの警告を監視できます。
ReportingObserver
ヘッダーと Reporting-Endpoints
ヘッダーは、同じレポートを生成しますが、ユースケースは若干異なります。
ReportingObserver
は、次の場合に使用します。
- 非推奨やブラウザによる介入のみをモニタリングする場合。
ReportingObserver
は、非推奨やブラウザの介入などのクライアント側の警告を表示しますが、Reporting-Endpoints
とは異なり、CSP や COOP/COEP 違反など、他のタイプのレポートはキャプチャしません。 - こうした違反にはリアルタイムで対応する必要があります。
ReportingObserver
を使用すると、違反イベントにコールバックをアタッチできます。 - カスタム コールバックを使用して、デバッグに役立つ追加情報をレポートに添付します。
別の違いは、ReportingObserver
はクライアントサイドでのみ構成されることです。サーバーサイド ヘッダーを制御できず、Reporting-Endpoints
を設定できない場合でも使用できます。
関連情報
- Reporting API v0 から v1 への移行ガイド
- ReportingObserver
- 仕様: 以前の Reporting API(v0)
- 仕様: 新しい Reporting API(v1)
Unsplash の Nine Koepfer / @enka80 によるヒーロー画像を編集。この記事のレビューと提案をしてくれた Ian Clelland、Eiji Kitamura、Miliica Mihajlija に感謝します。