Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FF130 CSP report-to directive #35331

Merged
merged 13 commits into from
Aug 23, 2024
2 changes: 1 addition & 1 deletion files/en-us/mozilla/firefox/releases/108/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ No notable changes
- [`Content-Security-Policy`](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) HTTP header directives [`script-src-elem`](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src-elem) and [`script-src-attr`](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src-attr) are now supported.
A server can use these to specify valid sources for JavaScript `<script>` elements, and for inline script event handlers like `onclick`, respectively ([Firefox bug 1529337](https://bugzil.la/1529337)).
- [`Content-Security-Policy`](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) violation reports now include `effective-directive` and `status-code` properties.
For more information, see [Violation report syntax](/en-US/docs/Web/HTTP/CSP#violation_report_syntax) ([Firefox bug 1192684](https://bugzil.la/1192684)).
For more information, see [Violation report syntax](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-uri#violation_report_syntax) ([Firefox bug 1192684](https://bugzil.la/1192684)).

### APIs

Expand Down
93 changes: 87 additions & 6 deletions files/en-us/web/api/cspviolationreportbody/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@ page-type: web-api-interface
browser-compat: api.CSPViolationReportBody
---

{{APIRef("Reporting API")}}{{SecureContext_Header}}
{{APIRef("Reporting API")}} {{SecureContext_Header}}

The `CSPViolationReportBody` interface contains the report data for a Content Security Policy (CSP) violation. CSP violations are thrown when the webpage attempts to load a resource that violates the CSP set by the {{HTTPHeader("Content-Security-Policy")}} HTTP header.
The `CSPViolationReportBody` interface is an extension of the [Reporting API](/en-US/docs/Web/API/Reporting_API) that represents the body of a Content Security Policy (CSP) violation report.

CSP violations are thrown when the webpage attempts to load a resource that violates the policy set by the {{HTTPHeader("Content-Security-Policy")}} HTTP header.

CSP violation reports are returned in the [reports](/en-US/docs/Web/API/ReportingObserver/ReportingObserver#reports) parameter of {{domxref("ReportingObserver")}} callbacks that have a `type` of `"csp-violation"`.
The `body` property of those reports is an instance of `CSPViolationReportBody`.

CSP violation reports may also be sent as JSON objects to the endpoint specified in the [`report-to`](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-to) policy directive of the {{HTTPHeader("Content-Security-Policy")}} header.
These reports similarly have a `type` of `"csp-violation"`, and a `body` property containing a serialization of an instance of this interface.

> [!NOTE]
> This interface is similar, but not identical to, the [JSON objects](/en-US/docs/Web/HTTP/CSP#violation_report_syntax) sent back to the [`report-uri`](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-uri) or [`report-to`](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-to) policy directive of the {{HTTPHeader("Content-Security-Policy")}} header.
> CSP violation reports sent by the Reporting API, when an endpoint is specified using the CSP [`report-to`](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-to) directive, are similar (but not identical) to the "CSP report" [JSON objects](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-uri#violation_report_syntax) sent when endpoints are specified using the [`report-uri`](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-uri) directive.
> The Reporting API and `report-to` directive are intended to replace the older report format and the `report-uri` directive.

{{InheritanceDiagram}}

Expand Down Expand Up @@ -52,7 +61,8 @@ _Also inherits methods from its parent interface, {{DOMxRef("ReportBody")}}._

### Obtaining a `CSPViolationReportBody` object

To obtain a `CSPViolationReportBody` object, you must configure your page so that a CSP violation will occur. In this example, we will set our CSP to only allow content from the site's own origin, and then attempt to load a script from `apis.google.com`, which is an external origin.
To obtain a `CSPViolationReportBody` object, you must configure your page so that a CSP violation will occur.
In this example, we will set our CSP to only allow content from the site's own origin, and then attempt to load a script from `apis.google.com`, which is an external origin.

First, we will set our {{HTTPHeader("Content-Security-Policy")}} header:

Expand All @@ -67,12 +77,12 @@ Then, we will attempt to load an external script:
<script src="https://apis.google.com/js/platform.js"></script>
```

Finally, we will create a new {{domxref("ReportingObserver")}} object to listen for CSP violations.
Finally, we will create a new {{domxref("ReportingObserver")}} object to listen for CSP violations (this will need to be loaded from the same location, before the script that causes the violation).

```js
const observer = new ReportingObserver(
(reports, observer) => {
const cspViolation = reports[0].body;
const cspViolation = reports[0];
},
{
types: ["csp-violation"],
Expand All @@ -83,6 +93,77 @@ const observer = new ReportingObserver(
observer.observe();
```

If we were to log the violation report object, it would look similar to the object below.
Note that the `body` is an instance of the `CSPViolationReportBody` and the `type` is `"csp-violation"`.

```js
{
"type": "csp-violation",
"url": "http://127.0.0.1:9999/",
"body": {
"sourceFile": null,
"lineNumber": null,
"columnNumber": null,
"documentURL": "http://127.0.0.1:9999/",
"referrer": "",
"blockedURL": "https://apis.google.com/js/platform.js",
"effectiveDirective": "script-src-elem",
"originalPolicy": "default-src 'self';",
"sample": "",
"disposition": "enforce",
"statusCode": 200
}
}
```

### Sending a CSP violation report

Configuring a web page to send a CSP violation report is similar to the previous example.
As before, you need to configure your page so that there is a violation.

In addition, you also need to specify the endpoint(s) where the report will be sent.
A server specifies endpoints using the {{httpheader("Reporting-Endpoints")}} response header: these must be secure URLs (HTTPS).
The CSP {{CSP("report-to")}} directive is then used to specify that a particular endpoint is used for reporting CSP violations:

```http
Reporting-Endpoints: csp-endpoint="https://example.com/csp-report-to"
Content-Security-Policy: default-src 'self'; report-to csp-endpoint
```

As before, we can trigger the violation by loading an external script from a location that is not allowed by our CSP header:

```html
<!-- This should generate a CSP violation -->
<script src="https://apis.google.com/js/platform.js"></script>
```

The violation report will then be sent to the indicated endpoint as a JSON file.
As you can see from the example below, the `type` is `"csp-violation"` and the `body` property is a serialization of the `CSPViolationReportBody` object:

```json
[
{
"age": 53531,
"body": {
"blockedURL": "inline",
"columnNumber": 59,
"disposition": "enforce",
"documentURL": "https://example.com/csp-report-to",
"effectiveDirective": "script-src-elem",
"lineNumber": 1441,
"originalPolicy": "default-src 'self'; report-to csp-endpoint",
"referrer": "https://www.google.com/",
"sample": "console.log(\"lo\")",
"sourceFile": "https://example.com/csp-report-to",
"statusCode": 200
},
"type": "csp-violation",
"url": "https://example.com/csp-report-to",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
}
]
```

## Specifications

{{Specifications}}
Expand Down
3 changes: 2 additions & 1 deletion files/en-us/web/api/report/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Reports can be accessed in a number of ways:

- Via the {{domxref("ReportingObserver.takeRecords()")}} method — this returns all reports in an observer's report queue, and then empties the queue.
- Via the `reports` parameter of the callback function passed into the [`ReportingObserver()`](/en-US/docs/Web/API/ReportingObserver/ReportingObserver) constructor upon creation of a new observer instance. This contains the list of reports currently contained in the observer's report queue.
- By sending requests to the endpoints defined via the {{httpheader("Report-To")}} HTTP header.
- By sending requests to the endpoints defined via the {{httpheader("Reporting-Endpoints")}} HTTP header.

## Instance properties

Expand Down Expand Up @@ -98,3 +98,4 @@ The `reports` parameter contains an array of all the reports in the observer's r
## See also

- [Reporting API](/en-US/docs/Web/API/Reporting_API)
- {{httpheader("Report-To")}} HTTP header
55 changes: 46 additions & 9 deletions files/en-us/web/api/reporting_api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,51 @@ There are several different features and problems on the web platform that gener
- Occurrence of crashes.
- Occurrence of user-agent interventions (when the browser blocks something your code is trying to do because it is deemed a security risk for example, or just plain annoying, like auto-playing audio).

The Reporting API's purpose is to provide a consistent reporting mechanism that can be used to make such information available to developers in the form of reports represented by JavaScript objects. There are a few ways to use it, which are detailed in the sections below.
The purpose of the Reporting API is to provide a consistent reporting mechanism that can be used to make such information available to developers in the form of reports represented by JavaScript objects. There are a few ways to use it, which are detailed in the sections below.

### Origins and endpoints
### Reporting server endpoints

Each unique origin you want to retrieve reports for can be given a series of endpoints, which are URLs that can receive given reports from a user agent.
Each unique origin you want to get reports for can be given a series of "endpoints", which are named URLs (or groups of URLs) that can be sent reports from a user agent.
A reporting server at these endpoints can collect the reports, and process and present them as needed by your application.

The {{httpheader("Report-To")}} HTTP header is used to specify details about the different endpoints that a user-agent has available to it for delivering reports to. You can then retrieve reports by making a request to those URLs.

The endpoints are arranged into groups; an endpoint group can work together to provide load balancing (each endpoint will receive a specified proportion of report traffic) and safeguarding against failure (fallback endpoints can be specified to use if the primary ones fail).
The {{httpheader("Reporting-Endpoints")}} HTTP header is used to specify details about the different endpoints that a user-agent has available to it for delivering reports.
The `report-to` directive can then be used on particular HTTP response headers to indicate the specific endpoint that will be used for the associated report.
For example, the CSP {{CSP("report-to")}} directive can be used on the {{HTTPHeader("Content-Security-Policy")}} or {{HTTPHeader("Content-Security-Policy-Report-Only")}} HTTP headers to specify the endpoint that CSP violation reports should be sent to.

> [!NOTE]
> There is no absolute guarantee of report delivery — a report could still fail to be collected if a serious error occurs.

The reports themselves are sent to the target endpoint by the user agent in a `POST` operation with a {{HTTPHeader("Content-Type")}} of `application/reports+json`.
They are serializations of {{domxref("Report")}} objects, where the `type` indicates the type of report, the `url` indicates the origin of the report, and the `body` contains a serialization of the API interface that corresponds to the report type.
For example, CSP violation reports have a `type` of `csp-violation` and a `body` that is a serialization of a {{domxref("CSPViolationReportBody")}} object.

Reports sent to endpoints can be retrieved independently of the running of the websites they relate to, which is useful — a crash for example could bring down a website and stop anything running, but a report could still be obtained to give the developer some clues as to why it happened.

### Reporting observers

Reports can also be obtained via {{domxref("ReportingObserver")}} objects created via JavaScript inside the website you are aiming to get reports on. This method is not as failsafe as the `Report-To` method described above — any page crash could stop you retrieving the reports — but it is easier to set up, and more flexible.
Reports can also be obtained via {{domxref("ReportingObserver")}} objects created via JavaScript inside the website you are aiming to get reports on.
This method is not as failsafe as sending reports to the server because any page crash could stop you retrieving the reports — but it is easier to set up, and more flexible.

A `ReportingObserver` object is created using the {{domxref("ReportingObserver.ReportingObserver", "ReportingObserver()")}} constructor, which is passed two parameters:

- A callback function that has available as parameters the reports available in the observer's report queue, and a copy of the same `ReportingObserver` object, so observation can be controlled directly from inside the callback. The callback runs when observation starts
- An options dictionary that allows you to specify the type of reports to collect, and whether the reports that were generated before the observer was able to be created should be observable (`buffered: true`).
- A callback function with two parameters — an array of the reports available in the observer's report queue and a copy of the same `ReportingObserver` object, which allows observation to be controlled directly from inside the callback. The callback runs when observation starts.
- An options dictionary that allows you to specify the type of reports to collect, and whether reports generated before the observer was created should be observable (`buffered: true`).

Methods are then available on the observer to start collecting reports ({{domxref("ReportingObserver.observe()")}}), retrieve the reports currently in the report queue ({{domxref("ReportingObserver.takeRecords()")}}), and disconnect the observer so it can no longer collect records ({{domxref("ReportingObserver.disconnect()")}}).

### Report types

Reports sent to reporting endpoints and reporting observers are essentially the same: they have an origin `url`, a `type`, and a `body` that is an instance of the interface corresponding with that type.
The only difference is that server reports are JSON serializations of the objects.

The mapping of report `type` to `body` is shown below.

| `type` | `body` | Items reported |
| --------------- | ------------------------------------- | -------------------------------------------------------------------------------- |
| `deprecation` | {{domxref("DeprecationReportBody")}} | Deprecated features used by the site. |
| `intervention` | {{domxref("InterventionReportBody")}} | Features blocked by the user agent, for example, if permissions are not granted. |
| `csp-violation` | {{domxref("CSPViolationReportBody")}} | Violations of the site's CSP policy. |

### Generating reports via WebDriver

The Reporting API spec also defines a Generate Test Report [WebDriver](/en-US/docs/Web/WebDriver) extension, which allows you to simulate report generation during automation. Reports generated via WebDriver are observed by any registered `ReportObserver` objects present in the loaded website. This is not yet documented.
Expand All @@ -71,8 +90,26 @@ These interfaces are defined as part of the HTTP [Content Security Policy (CSP)]
- {{domxref("SecurityPolicyViolationEvent")}}
- : Represents the event object of a `securitypolicyviolation` event fired on an element, document, or worker when its CSP is violated.

## Related HTTP Headers

These HTTP response headers define the endpoints where reports are sent.

- {{HTTPHeader("Reporting-Endpoints")}}
- : Sets the name and URL of reporting endpoints.
These can be used in the `report-to` directive, which may be used with a number of HTTP headers including {{httpheader("Content-Security-Header")}}.
- {{HTTPHeader("Report-To")}} {{deprecated_inline}}
- : Sets the name and URL of reporting endpoint groups, which may be used with a number of HTTP headers including `Content-Security-Header`.

Report endpoints can be set for the following reports using the `report-to` directive on the corresponding headers:

- CSP Violations

- : {{CSP("report-to")}} on {{HTTPHeader("Content-Security-Policy")}} or {{HTTPHeader("Content-Security-Policy-Report-Only")}}.

## Examples

### Reporting deprecated features

In our [deprecation_report.html](https://mdn.github.io/dom-examples/reporting-api/deprecation_report.html) example, we create a simple reporting observer to observe usage of deprecated features on our web page:

```js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ browser-compat: api.SecurityPolicyViolationEvent.sample

The **`sample`** read-only property of the {{domxref("SecurityPolicyViolationEvent")}} interface is a string representing a sample of the resource that caused the [Content Security Policy (CSP)](/en-US/docs/Web/HTTP/CSP) violation.

This is only [`script-src*`](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#script-src) and [`style-src*`](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#style-src) violations, when the corresponding `Content-Security-Policy` directive contains the [`'report-sample'`](/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#report-sample) keyword.
In addition, this will only be populated if the resource is an inline script, event handler, or style — external resources causing a violation will not generate a sample.

> [!NOTE] Violation reports should be considered attacker-controlled data.
> The content of this field should be sanitized before storing or rendering.

## Value

A string containing a sample of the resource that caused the violation, usually the first 40 characters.
This will only be populated if the resource is an inline script, event handler, or style — external resources causing a violation
will not generate a sample.
A string containing a sample of the resource that caused the violation, usually the first 40 characters, or the empty string.

## Examples

Expand Down
Loading