レポーティングAPI

W3C作業草案

この文書の詳細
このバージョン:
https://www.w3.org/TR/2025/WD-reporting-1-20250611/
最新公開バージョン:
https://www.w3.org/TR/reporting-1/
編集者草案:
https://w3c.github.io/reporting/
以前のバージョン:
履歴:
https://www.w3.org/standards/history/reporting-1/
フィードバック:
GitHub
仕様内でインライン
編集者:
(GitHub)
(Google Inc.)
(Google Inc.)
前編集者:
(Google Inc.)
(Google Inc.)

概要

この文書は、ウェブ開発者がオリジンに対して名前付きレポーティングエンドポイントのセットを関連付けることができる汎用レポーティングフレームワークを定義します。様々なプラットフォーム機能は、これらのエンドポイントを利用して、機能固有のレポートを一貫した方法で配信できます。

この文書の位置付け

このセクションでは、公開時点での文書の位置付けが説明されています。 現在のW3C出版物の一覧およびこの技術レポートの最新改訂版は W3C標準・草案一覧(https://www.w3.org/TR/)で確認できます。

この文書は Web Performance Working Groupによって、作業草案として勧告トラックに従って公開されました。 作業草案としての公開は、W3Cとその会員による承認を意味するものではありません。

この文書は草案であり、 今後更新・置換・廃止される可能性があります。 進行中の作業以外の目的でこの文書を引用することは適切ではありません。

GitHub Issuesは、この仕様に関する議論の場として推奨されています。

この文書は、2023年11月3日付W3Cプロセス文書に従って管理されています。

この文書は、W3C特許ポリシーのもとで運営されているグループによって作成されました。 W3Cは、グループの成果物に関して提出された特許開示の公開リストを管理しています。 そのページでは特許の開示方法についての案内も掲載されています。 個人が本質的な特許クレームを含むと考える特許について実際の知識を有している場合、 W3C特許ポリシー第6節に従って情報を開示する必要があります。

1. 導入

この文書は、汎用レポーティングのための3つのインフラを提供し、他の仕様によって利用・拡張される可能性があります:

  1. レポートタイプおよびレポーティングエンドポイントを定義するための汎用フレームワークと、HTTP経由でエンドポイントにレポートを送信するためのドキュメント形式。

  2. ドキュメントまたはワーカーでレポーティングエンドポイントを設定し、そのドキュメントまたはワーカーのライフタイムに紐づくレポートを配信するための具体的なメカニズム。

  3. ドキュメントやワーカー内で生成されたレポートを監視するためのJavaScriptインターフェイス。

他の仕様は、たとえば具体的なレポートタイプの定義や、非ドキュメントベースのレポートに対する別の設定・配信メカニズムの定義など、この仕組みを拡張・利用できます。

1.1. 保証事項

この仕様は、ウェブサイトの動作とは非同期に実行されるベストエフォートなレポート配信システムを提供することを目的とします。ユーザーエージェントは、個々のウェブサイトよりもクロスオリジンの活動を俯瞰できるため、レポートの配信の優先順位付けやスケジューリングをより適切に行うことができます。また、サイトの読み込み自体を阻害するようなエラー条件に基づいてレポートを配信することも可能です。

ただし、配信は何らかの方法で保証されるものではなく、レポーティングは信頼性の高い通信チャネルとして利用することを意図していません。ネットワーク状況により、レポートが目的地に到達しない場合があり、ユーザーエージェントは理由を問わずレポートの配信を拒否することも許可されています。

1.2.

MegaCorp Inc.は、Content Security PolicyとKey Pinning違反のレポートを収集したいと考えています。以下のヘッダーを配信することで、"endpoint-1"という名前のレポーティングエンドポイントのセットを定義できます:
Reporting-Endpoints: endpoint-1="https://example.com/reports"

そして、CSPとHPKPのレポートをそのエンドポイントに誘導するための以下のヘッダーを追加します:

Content-Security-Policy: ...; report-to endpoint-1
Public-Key-Pins: ...; report-to=endpoint-1
しばらくレポートを処理した後、MegaCorp Inc.はこれら2種類のレポート処理を2つの異なるエンドポイントに分割し、処理スクリプトを簡素化することにしました。次のヘッダーで2つのレポーティングエンドポイントを定義できます:
Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports",
                     hpkp-endpoint="https://example.com/hpkp-reports"

そして、CSPおよびHPKPレポートをそれぞれの名前付きエンドポイントに誘導する以下のヘッダーを追加します:

Content-Security-Policy: ...; report-to csp-endpoint
Public-Key-Pins: ...; report-to=hpkp-endpoint

2. 汎用レポーティングフレームワーク

このセクションでは、レポートとエンドポイントの汎用的な概念、およびレポートがapplication/reports+json形式にシリアライズされる方法について定義します。

2.1. 概念

2.1.1. エンドポイント

エンドポイントは、特定のレポートが 特定のオリジンに送信される場所です。

エンドポイントは、ASCII文字列のname属性を持ちます。

エンドポイントは、URL型のurl属性を持ちます。

エンドポイントは、リクエストへの応答に連続して失敗した回数を表す非負整数failures属性を持ちます。

2.1.2. レポートタイプ

レポートタイプは、レポート本文に含まれるデータの集合を指定する非空文字列です。

レポートタイプが(この仕様または他の仕様で)定義される際、ReportingObserverで可視と指定することができ、この場合、そのタイプのレポートレポーティングオブザーバーによって監視できます。デフォルトでは、レポートタイプReportingObserverで可視ではありません。

2.1.3. レポート

レポートは、ユーザーエージェントが指定されたエンドポイントへ配信することが期待される任意のデータの集合です。

レポートは、本文を持ちます。これはnullまたはJSONテキストとしてシリアライズ可能なオブジェクトです。含まれるフィールドはレポートタイプによって決まります。

レポートは、通常、レポートが生成されたDocumentまたはWorkerのアドレスであるurl属性を持ちます。

注: このシリアライズされたURLからはユーザー名・パスワード・フラグメントを除去します。詳細は§ 8.1 ケイパビリティURL参照。

レポートは、User-Agentヘッダーの値であるユーザーエージェント属性を持ちます。これは、そのレポートが生成されたリクエストUser-Agentです。

注: レポートのユーザーエージェントは、ページがレポートを生成した際に送信されたUser-Agentを表します。これは、レポートの収集時にHTTPヘッダーで送信されるUser-Agentと異なる場合があります(例:ブラウザが"デスクトップサイトをリクエスト"する場合など)。

レポートは、レポートが送信されるエンドポイントnameを表す文字列destination属性を持ちます。

レポートは、レポートタイプであるtype属性を持ちます。

レポートは、レポートが生成された時刻(UNIXエポックからのミリ秒)を記録するtimestamp属性を持ちます。

レポートは、ユーザーエージェントがレポートの配信を試みた回数を表す非負整数のattemptsカウンターを持ちます。

2.2. メディアタイプ

指定されたエンドポイントにレポートをPOSTする際のメディアタイプはapplication/reports+jsonです。

2.3. datatypeとしてdestinationにキューする

シリアライズ可能なオブジェクト(data)、文字列(type)、もう1つの文字列(destination)、オプションの環境設定オブジェクトsettings)、オプションのURLurl)を与えて、レポートを生成するには:

  1. reportを新規レポートオブジェクトとして、以下の値で初期化する:

    body

    data

    user agent

    現在のnavigator.userAgentの値

    destination

    destination

    type

    type

    timestamp

    現在のタイムスタンプ。

    attempts

    0

  2. もしurlが呼び出し元から提供されなかった場合、urlsettings作成URLとする。

  3. urlusernameを空文字列に、passwordnullに設定する。

  4. reporturlを、urlに対してフラグメント除外フラグを設定してURLシリアライザを実行した結果に設定する。

  5. reportを返す。

注: レポーティングオブザーバーは、同一環境設定オブジェクトからのレポートのみ監視できます。

注: レポートのシリアライズURLからユーザー名・パスワード・フラグメントを除去します。詳細は§ 8.1 ケイパビリティURL参照。

注: ユーザーエージェントは任意の理由でレポートを拒否できます。このAPIは任意の量のデータ配信を保証するものではありません。

注: JavaScriptエンジンを持たない非ユーザーエージェントクライアントはレポーティングオブザーバーとやりとりすべきではなく、ステップ6で終了してください。

2.4. レポートのシリアライズ

reportsのリストをJSONにシリアライズするには、

  1. collectionを空リストとする。

  2. reports内の各reportについて:

    1. 以下のキーと値からなるdataマップを作成する:

      age

      reporttimestampと現在時刻との差(ミリ秒)。

      type

      reporttype

      url

      reporturl

      user_agent

      reportuser agent

      body

      reportbody

      注: クライアントクロックは信頼性が低く、スキューが生じる可能性があります。そのため絶対的なタイムスタンプではなくage属性を配信します。詳細は§ 9.2 クロックスキュー参照。

    2. reportattemptsをインクリメントする。

    3. datacollectionに追加する。

  3. collectionに対してInfra値をJSONバイト列にシリアライズを実行した結果のバイト列を返す。

3. ドキュメント中心のレポーティング

このセクションでは、ドキュメント(またはワーカースクリプト)内の操作によって生成されたレポートに対して、レポーティングエンドポイントを設定する仕組みを定義します。これらのレポートは、それが生成されたドキュメントまたはワーカーのライフタイムに紐づきます。

3.1. ドキュメントの設定

WindowOrWorkerGlobalScope を実装する各オブジェクトは、endpointsリスト(エンドポイントのリスト)を持ち、各エンドポイントは異なるnameを持たなければなりません。(一意性は§ 3.3 レスポンスのレポーティングエンドポイント処理のアルゴリズムにより保証されます。)

WindowOrWorkerGlobalScope を実装する各オブジェクトは、reportsリスト(レポートのリスト)も持ちます。

グローバルのエンドポイントリストを初期化するには、WindowOrWorkerGlobalScope (scope)とresponseresponse)を与え、scopeendpointsresponseに対して§ 3.3 レスポンスのレポーティングエンドポイント処理を実行した結果に設定します。

サーバーは、返すドキュメントやワーカースクリプトリソースに対して、Reporting-Endpoints HTTPレスポンスヘッダーフィールドを用いてレポーティングエンドポイントのセットを定義することができます。この仕組みは§ 3.2 Reporting-Endpoints HTTPレスポンスヘッダーフィールドで定義され、処理方法は§ 3.3 レスポンスのレポーティングエンドポイント処理で規定されています。

Reporting-Endpoints HTTPレスポンスヘッダーフィールドの値は、リソースのレポーティング設定を構築するために使用されます。

Reporting-Endpointsは、辞書型構造化フィールド値(Dictionary Structured Field)[STRUCTURED-FIELDS]です。辞書の各エントリが、レポートを配信できるエンドポイントを定義します。エントリ値は文字列でなければなりません。

エンドポイントは文字列項目(String Item)によって定義され、URI参照として解釈されます。その値が有効なURI参照でない場合、そのエンドポイントは無視されなければなりません。

さらに、その値が示すURLは潜在的に信頼できるものでなければなりません[SECURE-CONTEXTS]。非セキュアなエンドポイントは無視されます。

エンドポイントにはパラメータは定義されておらず、指定されたパラメータは無視されます。

このヘッダーは次のABNF文法で表現されます[RFC5234]

Reporting-Endpoints = sf-dictionary

3.3. responseのレポーティングエンドポイントの処理

responseresponse)を与えると、このアルゴリズムはエンドポイントのリストを抽出して返します。

  1. responseHTTPS状態が"modern"でなく、かつresponseurlオリジン潜在的に信頼できるものでない場合、これらのステップを中止する。

  2. parsed headerを、responseヘッダーリストから"Reporting-Endpoints"および"dictionary"を与えて構造化フィールド値を取得した結果とする。

  3. parsed headerがnullなら、これらのステップを中止する。

  4. endpointsを空リストにする。

  5. parsed headerの各namevalue_and_parametersについて:

    1. endpoint url stringをタプルvalue_and_parametersの最初の要素とし、endpoint url stringが文字列でない場合はcontinueする。

    2. endpoint urlendpoint url stringに対してURLパーサーresponseurlを基準URLとして実行した結果とする。失敗した場合はcontinueする。

    3. endpoint urlオリジン潜在的に信頼できるものでなければ、continueする。

    4. endpointを新しいエンドポイントとして次の属性で初期化する:

      name

      name

      url

      endpoint url

      failures

      0

    5. endpointendpointsに追加する。

  6. endpointsを返す。

3.4. レポート生成

3.4.1. typeのレポートをdataで生成

ユーザーエージェントがDocument またはWorkerGlobalScope オブジェクト(context)、 文字列(type)、 文字列(destination)、 シリアライズ可能なオブジェクト(data)を与えられたとき、以下のステップを実行します:

  1. settingscontext関連設定オブジェクトとする。

  2. reportdatatypedestinationsettingsを与えてレポートを生成した結果とする。

  3. settingsが与えられていれば、

    1. scopesettingsグローバルオブジェクトとする。

    2. scopeWindowOrWorkerGlobalScope を実装するオブジェクトなら、§ 4.2 scopereportのレポーティングオブザーバー通知を実行する。

  4. reportcontextreportsに追加する。

3.5. レポート配信

時間の経過とともに、さまざまな機能がドキュメントやワーカー内にレポートをキューしていきます。ユーザーエージェントは定期的に現在キューされているレポートリストを取得し、関連エンドポイントに配信します。本仕様ではユーザーエージェントが従うべきスケジュールは定義せず、ユーザーエージェントが十分な文脈情報をもとに、ユーザー体験に影響しない範囲でタイムリーにレポートを配信できると仮定します。

とはいえ、ユーザーエージェントはキュー後できるだけ速やかにレポートを配信するよう努めるべきです。生成直後のレポートデータは、1日後や1週間後よりもはるかに有用である可能性があります。

3.5.1. レポート送信

ユーザーエージェントはWindowOrWorkerGlobalScope オブジェクト(context)のreportsreports)のリストを次のステップで送信します:

  1. endpoint mapエンドポイントオブジェクトからレポートオブジェクトのリストへの空マップとする。

  2. reports内の各reportについて:

    1. contextendpointsリスト内にreportdestinationと一致するnameを持つendpointが存在する場合:

      1. reportendpoint mapのそのendpointのレポートリストに追加する。

      2. 存在しない場合、reportreportsから削除する。

  3. endpoint mapの各(endpoint, report list)ペアについて:

    1. origin mapオリジンからレポートオブジェクトのリストへの空マップとする。

    2. report list内の各reportについて:

      1. originreporturlのオリジンとする。

      2. reportorigin mapのそのoriginのレポートリストに追加する。

    3. origin mapの各(origin, per-origin reports)ペアについて、次のステップを非同期に実行する:

      1. resultendpointoriginper-origin reportsを与えて§ 3.5.2 reportsendpointに配信試行を実行した結果とする。

      2. resultが"Failure"の場合:

        1. endpointfailuresをインクリメントする。

      3. resultが"Remove Endpoint"の場合:

        1. endpointcontextendpoints リストから削除する。

      4. reportreportsから削除する。

      失敗したレポートの再試行メカニズムはここでは指定していません。再試行手順や配信失敗の合図を追加することも検討すべきです。

注: ユーザーエージェントは収集したレポートやエンドポイントの一部だけ配信することを選択する場合があります(たとえば、すべてのレポートを一度に送信すると帯域消費が過大になる場合など)。レポートは配信が試みられた後にのみキャッシュから削除されるため、スキップされたレポートは後で配信されます。

3.5.2. reportsendpointに配信試行

endpoint (endpoint)、origin (origin)、reportsreports)のリストを与えると、このアルゴリズムはrequestを構築し、endpointへの配信を試みます。配信が成功すれば"Success"を、エンドポイントが410応答で自身を明示的に削除した場合は"Remove Endpoint"を、それ以外は"Failure"を返します。

  1. bodyreportsに対してレポートのJSONシリアライズを実行した結果とする。

  2. requestを次のプロパティで新規requestとして作成する[FETCH]

    method

    "POST"

    url

    endpointurl

    origin

    origin

    header list

    ヘッダーリストで、`Content-Type`ヘッダーの値を`application/reports+json`とするものを含む新規リスト

    client

    null

    window

    "no-window"

    service-workers mode

    "none"

    initiator

    ""

    destination

    "report"

    mode

    "cors"

    unsafe-request flag

    セット

    credentials

    "same-origin"

    body

    bodyで、sourcebodyにするもの。

    注: レポートはsame-originで送信されます。これにより、レポートページと同一オリジンのレポーティングエンドポイントは、例えば特定ユーザーのアカウントでエラーが頻発しているか、他のページでの一連の操作がこのページでのレポート発生につながっているかなど、追加のコンテキストを得られます。これは、他の手段でも取得可能な情報であり、新たな情報漏洩にはなりません。クロスオリジンのレポーティングエンドポイントには認証情報は送信されません。

  3. タスクをキューしてfetch requestを実行する。

  4. レスポンスを待つresponse)。

  5. responsestatusOKステータス (200-299)なら、"Success"を返す。

  6. responsestatus410 Goneなら[RFC9110]、"Remove Endpoint"を返す。

  7. "Failure"を返す。

3.6. レポート利用のためのURLの除去

レポート利用のためのURL除去は、URLurlを与え、以下のステップを実行します。返り値はレポートで利用するURLを表す文字列です。
  1. urlschemeHTTP(S) schemeでない場合、urlschemeを返す。

  2. urlfragmentを空文字列に設定する。

  3. urlusernameを空文字列に設定する。

  4. urlpasswordを空文字列に設定する。

  5. urlURLシリアライザを実行した結果を返す。

4. レポーティングオブザーバー

レポーティングオブザーバーは、JavaScriptから一部のレポートを監視し、JavaScriptではReportingObserverオブジェクトとして表現されます。

WindowOrWorkerGlobalScope を実装する各オブジェクトは、登録済みレポーティングオブザーバーリストを持ちます。 これは順序付き集合であり、レポーティングオブザーバーの集合です。

登録済みレポーティングオブザーバーリストに含まれる レポーティングオブザーバー登録済みとみなされます。

WindowOrWorkerGlobalScope を実装する各オブジェクトは、レポートバッファも持ちます。これは、そのWindowOrWorkerGlobalScopeで生成されたレポートリストであり、初期状態は空で、生成順に保存されます。

注: レポートバッファの目的は、レポーティングオブザーバーが生成時点より前に生成されたレポートも監視できるようにすることです(bufferedオプションを利用)。たとえば、ページの読み込み初期段階やJavaScriptライブラリのロード前に生成されたレポートなどを監視できます。

注: レポーティングオブザーバーはJavaScriptエンジンを持つユーザーエージェントのみが対象です。

4.1. インターフェイス ReportingObserver

dictionary ReportBody {
};

dictionary Report {
  DOMString type;
  DOMString url;
  ReportBody? body;
};

[Exposed=(Window,Worker)]
interface ReportingObserver {
  constructor(ReportingObserverCallback callback, optional ReportingObserverOptions options = {});
  undefined observe();
  undefined disconnect();
  ReportList takeRecords();
};

callback ReportingObserverCallback = undefined (sequence<Report> reports, ReportingObserver observer);

dictionary ReportingObserverOptions {
  sequence<DOMString> types;
  boolean buffered = false;
};

typedef sequence<Report> ReportList;

Reportは、レポートのアプリケーション公開表現です。

ReportBodyは、具体的なレポートタイプが継承するべき抽象dictionary型です。

ReportingObserverオブジェクトには次の概念が紐付いています:

ReportListReportの配列を表し、JavaScript配列の便利なメソッドを全て利用できます。

ReportingObserver(callback, options) コンストラクターが呼び出されたとき、次の手順を実行します:

  1. 新規ReportingObserverオブジェクトobserverを作成する。

  2. observerコールバックcallbackを設定する。

  3. observeroptionsoptionsを設定する。

  4. observerを返す。

observe()メソッドが呼び出されたとき、次の手順を実行します:

  1. global該当グローバルオブジェクトthisの)とする。

  2. thisglobal登録済みレポーティングオブザーバーリストに追加する。

  3. thisbuffered optionがfalseなら、return。

  4. thisbuffered optionをfalseにする。

  5. globalレポートバッファ内の各reportについて、タスクをキュー§ 4.3 reportをobserverに追加reportthisで実行する。

disconnect()メソッドが呼び出されたとき、次の手順を実行します:

  1. this登録済みでなければ、return。

  2. global該当グローバルオブジェクトthisの)とする。

  3. thisglobal登録済みレポーティングオブザーバーリストから削除する。

takeRecords()メソッドが呼び出されたとき、次の手順を実行します:

  1. reportsthisレポートキューのコピーとする。

  2. thisレポートキューを空にする。

  3. reportsを返す。

4.2. scopereportのレポーティングオブザーバー通知

このアルゴリズムは、reportの内容を、指定されたWindowOrWorkerGlobalScope上の、いずれかの登録済みレポーティングオブザーバーに利用可能にします。

  1. scope登録済みの各ReportingObserver observerについて、§ 4.3 オブザーバーへのレポート追加reportobserverに対して実行する。

  2. reportscopeレポートバッファに追加する。

  3. typereporttypeとする。

  4. もしscopeレポートバッファが、typeが等しいtypeのレポートを100件より多く含むようになった場合、レポートバッファ内のtypeが等しいtypeを持つ最も早い項目を削除する。

4.3. reportobserverに追加

report reportReportingObserver observerが与えられた場合、このアルゴリズムは、reporttypeobserverによって観測可能である限り、reportobserverレポートキューに追加します。

  1. reporttypeReportingObserverで可視でなければ、return。

  2. observeroptionstypesメンバーが空でなく、かつreporttypeを含まない場合はreturn。

  3. 新規Report rを作成し、typereporttypeurlreporturlbodyreportbodyを初期化する。

bodyの多態的初期化方法?

  1. robserverレポートキューに追加する。

  2. observerレポートキューのサイズが1なら:

    1. globalobserver該当グローバルオブジェクトとする。

    2. タスクをキューして、§ 4.4 notify listでレポーティングオブザーバー呼び出しglobal登録済みレポーティングオブザーバーリストのコピーで実行する。

4.4. notify listでレポーティングオブザーバー呼び出し

このアルゴリズムは、過去の監視された動作についてオブザーバーのコールバック関数を呼び出します。

  1. notify list内の各ReportingObserver observerについて:

    1. observerレポートキューが空ならcontinue。

    2. reportsobserverレポートキューのコピーとする。

    3. observerレポートキューを空にする。

    4. コールバック関数の呼び出しobserverコールバック、« reports, observer »、"report"、およびobserverコールバックthis値として実行する。

5. 実装上の考慮事項

5.1. 配信

ユーザーエージェントは可能な限り迅速にレポートを配信し、開発者に素早くフィードバックを提供するべきです。しかし、この要望はユーザーへの影響とのバランスが取られ、最終的にはユーザーが優先されます。そのため、ユーザーエージェントはユーザーの活動やコンテキストに関する知識に基づき、レポートの配信を遅延させても構いません。

たとえば、ユーザーエージェントはレポーティングデータの送信を他のネットワークトラフィックよりも低い優先順位で処理すべきです。ユーザーがウェブサイト上で明示的に行う活動は、レポーティングトラフィックよりも優先されます。

ユーザーエージェントは、不要なデータコストを防ぐため、ユーザーが高速かつ安価なネットワークに接続している場合までレポートの配信を完全に保留することもできます。

ユーザーエージェントは、特定のオリジン(たとえば、ユーザーが頻繁に訪問するもの)のレポートを他より優先して配信することも許可されています。

5.2. ガベージコレクション

定期的に、ユーザーエージェントはキャッシュされたレポートエンドポイントを巡回し、もはや関連しないものを破棄するべきです。これには次が含まれます:

破棄されたレポートは、すべてのレポートレポートバッファからも削除するべきです。

6. サンプルレポート

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

この例は、ユーザーエージェントがレポーティングエンドポイントに送信するレポートのフォーマットを示しています。サンプル送信には3つのレポートがまとめられ、単一のHTTPリクエストで送信されています(レポートのタイプや本文自体は、実際の機能を示すものではなく、本仕様の範囲外であることに留意してください)。

POST / HTTP/1.1
Host: example.com
...
Content-Type: application/reports+json

[{
  "type": "security-violation",
  "age": 10,
  "url": "https://example.com/vulnerable-page/",
  "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0",
  "body": {
    "blocked": "https://evil.com/evil.js",
    "policy": "bad-behavior 'none'",
    "status": 200,
    "referrer": "https://evil.com/"
  }
}, {
  "type": "certificate-issue",
  "age": 32,
  "url": "https://www.example.com/",
  "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0",
  "body": {
    "date-time": "2014-04-06T13:00:50Z",
    "hostname": "www.example.com",
    "port": 443,
    "effective-expiration-date": "2014-05-01T12:40:50Z",
    "served-certificate-chain": [
      "-----BEGIN CERTIFICATE-----\n
      MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\n
      ...
      HFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto\n
      WHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6\n
      yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx\n
      -----END CERTIFICATE-----",
      ...
    ]
  }
}, {
  "type": "cpu-on-fire",
  "age": 29,
  "url": "https://example.com/thing.js",
  "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0",
  "body": {
    "temperature": 614.0
  }
}]

7. 自動化

ユーザーエージェントの自動化やアプリケーションテストの目的で、本書は拡張コマンド[WebDriver]仕様に定義します。

7.1. テストレポート生成

Generate Test Report 拡張コマンドは、テストのためにレポートの生成をシミュレートします。このレポートは、すべての登録済みレポーティングオブザーバーによって監視されます。

この拡張コマンドは以下のように定義されています:

dictionary GenerateTestReportParameters {
  required DOMString message;
  DOMString group = "default";
};
HTTPメソッド URIテンプレート
POST /session/{session id}/reporting/generate_test_report

リモートエンド手順は以下の通りです:

  1. parametersがJSONオブジェクトでない場合、WebDriverエラーWebDriverエラーコードinvalid argumentとともに返す。

  2. messageparametersmessageプロパティからtryで取得する。

  3. messageが存在しない場合、WebDriverエラーWebDriverエラーコードinvalid argumentとともに返す。

  4. 現在のブラウジングコンテキストがすでに閉じられている場合、WebDriverエラーWebDriverエラーコードno such windowとともに返す。

  5. ユーザープロンプトを処理し、その値がWebDriverエラーなら返す。

  6. groupparametersgroupプロパティとする。

  7. bodyを、JSONテキストにシリアライズ可能な新規オブジェクトとして作成し、1つの文字列フィールドbody_messageを持たせる。

  8. body_messagemessageを設定する。

  9. settingsを、環境設定オブジェクト現在のブラウジングコンテキストアクティブドキュメントの)とする。

  10. body、"test"、groupsettingsレポート生成&キューを実行する。

  11. success(データなし)を返す。

8. セキュリティに関する考慮事項

8.1. ケイパビリティURL

一部のURLはそれ自体が価値を持っています。URLのユーザー名やパスワード部分に明示的な認証情報が含まれていたり、URLパスを知っているだけでリソースへのアクセスが可能だったりします。また、URLのフラグメントにはブラウザ外に出すことを意図していない情報が含まれる場合もあります。詳細は[CAPABILITY-URLS]を参照してください。

このレポーティングメカニズムによるURL漏洩の可能性を軽減するため、ここで定義するアルゴリズムでは、レポート送信元のURLから認証情報およびフラグメントデータを除去します。ただし、URLパスに含まれる機密情報がこの方法で漏洩する可能性は残ります。このようなURLを利用するサイトは、自前のレポーティングエンドポイントを運用する必要があるかもしれません。

さらに、こうしたURLがレポートの本文に含まれている場合もあります。このAPIを拡張する仕様でレポートの本文にURLを含める際は、同様に除去することを要求すべきです。

9. プライバシーに関する考慮事項

9.1. ネットワーク漏洩

ページが読み込まれてからレポートが生成・送信されるまでに遅延があるため、ユーザーがあるネットワーク上で生成されたレポートが、別のネットワーク上で送信される可能性があります。

この振る舞いは、レポートを生成したドキュメントのライフタイムに限定されますが、たとえドキュメントが閉じられた後でも、navigator.sendBeaconなどの仕組みを通じて新しいネットワーク上でトラフィックを発生させることが可能です。

対策検討事項。例えば、ネットワークが切り替わった場合にレポートを破棄するなど。[WICG/background-sync Issue #107]

9.2. クロックスキューによるフィンガープリント

レポートは生成時刻のタイムスタンプではなくageプロパティとともに配信されます。これは、各ユーザーのローカルクロックがサーバーのクロックと任意量だけずれているためです。レポートの生成時刻と送信時刻の差はクロックスキューにかかわらず安定しており、このAPIでクロックスキューがフィンガープリントとして露呈するリスクを避けることができます。

9.3. クロスオリジン相関

複数のオリジンが同じレポーティングエンドポイントを利用すると、そのエンドポイントは特定ユーザーがどのウェブサイトにアクセスしたかを知ることができます。オリジンごとにタグ付けされたレポートが送信されるためです。これは、協力的なオリジンによる現状の追跡能力と比べて悪化するものではなく、<img>等で既に可能な追跡能力以上を付与するものではありません。

9.4. レポーティングの無効化

レポーティングは、ある意味でコモンズの問題です。全体として、レポートが配信されることは皆にとって有益です。開発者はバグを修正でき、ユーザーはより安定したサイトを享受できます。例えば、Content Security Policyはクロスサイトスクリプティング攻撃に対して集団免疫のような効果をもたらし、開発者にサイト防御の穴を警告します。バグ修正はすべてのユーザーに恩恵をもたらします。

もちろん、送信されるデータの性質やレポーティングエンドポイントの悪意の程度によって計算は変わりますが、概ねこのような利得構造です。

とはいえ、この一般的な利得が、ユーザーが個別にシステムをオプトアウトする能力よりも優先されるべきではありません。レポートの送信は帯域を消費し、ウェブサイトがin-bandで取得できる情報以上のものを若干漏洩する可能性もあります(例えば[NETWORK-ERROR-LOGGING]など)。ユーザーエージェントは、[HTML-DESIGN-PRINCIPLES]に記載された優先順位を守るため、ユーザーが合理的な粒度でレポーティングを無効化できるようにしなければなりません。

10. IANAに関する考慮事項

10.1. Reporting-Endpointsヘッダー

恒久的なメッセージヘッダーフィールドレジストリは、以下の登録で更新されるべきです。[RFC3864]

ヘッダーフィールド名

Reporting-Endpoints

適用プロトコル

http

ステータス

standard

著者/変更管理者

W3C

仕様書

本仕様(§ 3.2 Reporting-Endpoints HTTPレスポンスヘッダーフィールド参照)

10.2. application/reports+jsonメディアタイプ

タイプ名

application

サブタイプ名

reports+json

必須パラメータ

N/A

オプションパラメータ

N/A

エンコーディングに関する考慮事項

エンコーディングに関する考慮事項は "application/json" メディアタイプで指定されたものと同一です。[RFC8259]参照。

セキュリティに関する考慮事項

§ 8 セキュリティに関する考慮事項参照。

相互運用性に関する考慮事項

本書は準拠メッセージのフォーマットおよびその解釈を規定します。

公開仕様

§ 2.2 メディアタイプ

このメディアタイプを利用するアプリケーション
フラグメント識別子に関する考慮事項
追加情報

N/A

追加情報問い合わせ先

本書の編集者。

利用目的

COMMON

利用制限

N/A

著者

本書の編集者。

変更管理者

W3C

暫定登録?

Yes.

索引

本仕様で定義された用語

他で定義された用語

参考文献

標準文献

[DOM]
Anne van Kesteren. DOM標準。現行標準。 URL: https://dom.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch標準。現行標準。URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML標準。 現行標準。URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra標準。現行標準。URL: https://infra.spec.whatwg.org/
[RDF12-CONCEPTS]
Olaf Hartig; et al. RDF 1.2 概念と抽象構文。2025年6月6日。WD。URL: https://www.w3.org/TR/rdf12-concepts/
[RFC3864]
G. Klyne; M. Nottingham; J. Mogul. メッセージヘッダーフィールド登録手続き。2004年9月。Best Current Practice。URL: https://www.rfc-editor.org/rfc/rfc3864
[RFC5234]
D. Crocker, Ed.; P. Overell. 構文仕様のための拡張BNF: ABNF。2008年1月。Internet Standard。URL: https://www.rfc-editor.org/rfc/rfc5234
[RFC8259]
T. Bray, Ed.. JavaScriptオブジェクト記法 (JSON) データ交換フォーマット。2017年12月。Internet Standard。URL: https://www.rfc-editor.org/rfc/rfc8259
[RFC9110]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. HTTPセマンティクス。2022年6月。Internet Standard。URL: https://httpwg.org/specs/rfc9110.html
[SECURE-CONTEXTS]
Mike West; Yan Zhu. セキュアコンテキスト。URL: https://w3c.github.io/webappsec-secure-contexts/
[STRUCTURED-FIELDS]
Mark Nottingham; Poul-Henning Kamp. HTTPの構造化フィールド値。URL: https://www.rfc-editor.org/rfc/rfc8941.html
[URL]
Anne van Kesteren. URL標準。現行標準。URL: https://url.spec.whatwg.org/
[WebDriver]
Simon Stewart; David Burns. WebDriver。2018年6月5日。REC。URL: https://www.w3.org/TR/webdriver1/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL標準。現行標準。URL: https://webidl.spec.whatwg.org/

参考文献

[CAPABILITY-URLS]
Jeni Tennison. ケイパビリティURLのベストプラクティス。2014年2月18日。FPWD。URL: https://www.w3.org/TR/capability-urls/
[CSP3]
Mike West; Antonio Sartori. Content Security Policy Level 3。2025年6月6日。WD。URL: https://www.w3.org/TR/CSP3/
[HTML-DESIGN-PRINCIPLES]
Anne van Kesteren; Maciej Stachowiak. HTMLデザイン原則。2007年11月26日。WD。URL: https://www.w3.org/TR/html-design-principles/
[NETWORK-ERROR-LOGGING]
Douglas Creager; Ian Clelland. ネットワークエラーロギング。2025年5月5日。WD。URL: https://www.w3.org/TR/network-error-logging/
[RFC7469]
C. Evans; C. Palmer; R. Sleevi. HTTPのための公開鍵ピン拡張。2015年4月。Proposed Standard。URL: https://www.rfc-editor.org/rfc/rfc7469

IDL索引

dictionary ReportBody {
};

dictionary Report {
  DOMString type;
  DOMString url;
  ReportBody? body;
};

[Exposed=(Window,Worker)]
interface ReportingObserver {
  constructor(ReportingObserverCallback callback, optional ReportingObserverOptions options = {});
  undefined observe();
  undefined disconnect();
  ReportList takeRecords();
};

callback ReportingObserverCallback = undefined (sequence<Report> reports, ReportingObserver observer);

dictionary ReportingObserverOptions {
  sequence<DOMString> types;
  boolean buffered = false;
};

typedef sequence<Report> ReportList;

dictionary GenerateTestReportParameters {
  required DOMString message;
  DOMString group = "default";
};

課題索引

失敗したレポートの再試行メカニズムはここでは指定していません。再試行手順や配信失敗の合図を追加することも検討すべきです。
bodyの多態的初期化方法?
対策検討事項。例えば、ネットワークが切り替わった場合にレポートを破棄するなど。 [WICG/background-sync Issue #107]
MDN

Report/body

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Report/type

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Report/url

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Report

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ReportBody

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ReportingObserver/ReportingObserver

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ReportingObserver/disconnect

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ReportingObserver/observe

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ReportingObserver/takeRecords

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

ReportingObserver

FirefoxNoneSafari16.4+Chrome69+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?