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

Hash reporting for scripts #693

Merged
merged 18 commits into from
Dec 6, 2024
99 changes: 95 additions & 4 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ Markup Shorthands: css off, markdown on
At Risk: The [[#is-element-nonceable]] algorithm.
</pre>
<pre class="link-defaults">
spec:dom; type:interface; text:Document
spec:dom;
type: interface
text: Document
type: dfn
text: URL; url: https://dom.spec.whatwg.org/#dom-document-url
spec:html
type: dfn
text: fallback base url
Expand Down Expand Up @@ -164,6 +168,11 @@ spec: WebRTC; urlPrefix: https://www.w3.org/TR/webrtc/
type:dfn
text: administratively-prohibited; url: #dfn-administratively-prohibited

spec:SRI; urlPrefix: https://w3c.github.io/webappsec-subresource-integrity
type:dfn;
text:applying algorithm to bytes; url: #apply-algorithm-to-response
text: cryptographic hash function; url: #hash-functions

</pre>
<pre class="biblio">
{
Expand All @@ -182,7 +191,7 @@ spec: WebRTC; urlPrefix: https://www.w3.org/TR/webrtc/
"REPORTING": {
"href": "https://wicg.github.io/reporting/",
"title": "Reporting API",
"authors": [ "Ilya Gregorik", "Mike West" ]
"authors": [ "Ilya Grigorik", "Mike West" ]
},
"TIMING": {
"href": "https://owasp.org/www-pdf-archive/HackPra_Allstars-Browser_Timing_Attacks_-_Paul_Stone.pdf",
Expand Down Expand Up @@ -682,9 +691,10 @@ spec: WebRTC; urlPrefix: https://www.w3.org/TR/webrtc/

; Keywords:
<dfn>keyword-source</dfn> = "<dfn>'self'</dfn>" / "<dfn>'unsafe-inline'</dfn>" / "<dfn>'unsafe-eval'</dfn>"
/ "<dfn>'strict-dynamic'</dfn>" / "<dfn>'unsafe-hashes'</dfn>" /
/ "<dfn>'strict-dynamic'</dfn>" / "<dfn>'unsafe-hashes'</dfn>"
/ "<dfn>'report-sample'</dfn>" / "<dfn>'unsafe-allow-redirects'</dfn>"
/ "<dfn>'wasm-unsafe-eval'</dfn>"
/ "<dfn>'wasm-unsafe-eval'</dfn>" / "<dfn>'report-sha256'</dfn>"
yoavweiss marked this conversation as resolved.
Show resolved Hide resolved
/ "<dfn>'report-sha384'</dfn>" / "<dfn>'report-sha512'</dfn>"

ISSUE: Bikeshed `unsafe-allow-redirects`.

Expand Down Expand Up @@ -1089,6 +1099,44 @@ spec: WebRTC; urlPrefix: https://www.w3.org/TR/webrtc/

4. Return |result|.

<h4 id="potentially-report-hash" algorithm dfn export>Potentially report hash</h4>

Given a [=response=] |response|, a [=/request=] |request|, a [=directive=] |directive| and a
[=content security policy object=] |policy|, run the following steps:

1. Let |algorithm| be the empty [=string=].
1. If |directive|'s <a for="directive">value</a> <a for="list">contains</a> the
yoavweiss marked this conversation as resolved.
Show resolved Hide resolved
expression "<a grammar>`'report-sha256'`</a>", set |algorithm| to "sha256".
1. If |directive|'s <a for="directive">value</a> <a for="list">contains</a> the
expression "<a grammar>`'report-sha384'`</a>", set |algorithm| to "sha384".
1. If |directive|'s <a for="directive">value</a> <a for="list">contains</a> the
expression "<a grammar>`'report-sha512'`</a>", set |algorithm| to "sha512".
1. If |algorithm| is the empty [=string=], return.
1. Let |hash| be the empty [=string=].
1. If |response| is [=CORS-same-origin=], then:
1. Let |hash list| be a [=list=] of [=strings=], initially empty.
1. [=list/Append=] |algorithm| to |hash list|.
1. [=list/Append=] the result of [=applying algorithm to bytes=] on |response|'s
[=response/body=] and |algorithm| to |hash list|.
1. Let |hash| be the result of [=concatenating=] |hash list| with U+002D (-).
1. Let |document URL| be the empty [=string=].
1. Let |global| be the |request|'s [=request/client=]'s [=/global object=].
1. If |global| is a {{Window}}, set |document URL| to |global|'s [=document=]'s [=Document/URL=].
yoavweiss marked this conversation as resolved.
Show resolved Hide resolved
1. If |policy|'s [=directive set=] does not contain a [=directive=] named "report-to", return.
1. Let |report-to directive| be a [=directive=] named "report-to" from |policy|'s [=directive
set=].
1. Let |body| be a [=csp hash report body=] with |document URL| as its [=documentURL=],
yoavweiss marked this conversation as resolved.
Show resolved Hide resolved
|request|'s URL as its [=subresourceURL=], |hash| as its
[=hash=], and "subresource" as its [=csp hash report body/type=].
1. [=Generate and queue a report=] with the following arguments:
antosart marked this conversation as resolved.
Show resolved Hide resolved
: <var ignore>context</var>
:: <var ignore>settings object</var>
: <var ignore>type</var>
:: "csp-hash"
: <var ignore>destination</var>
:: |report-to directive|'s [=directive/value=].
: <var ignore>data</var>
:: |body|

<h3 id="html-integration">
Integration with HTML
Expand Down Expand Up @@ -1593,6 +1641,48 @@ this algorithm returns normally if compilation is allowed, and throws a
};
</pre>

When a directive that impacts [=script-like=] [=request/destinations=] has a `report-hash` value,
yoavweiss marked this conversation as resolved.
Show resolved Hide resolved
and a [=/request=] with a [=script-like=] [=request/destination=] is fetched, a <dfn export>csp
hash report</dfn> will be generated and sent out to a reporting endpoint associated with the <a
for="/">policy</a>.

<p><a>csp hash reports</a> have the <a>report type</a> "csp-hash".</p>

<p><a>csp hash reports</a> are not <a>visible to <code>ReportingObserver</code>s</a>.

<p>A <dfn>csp hash report body</dfn> is a [=struct=] with the following fields:
<dfn for="csp hash report body">documentURL</dfn>,
<dfn for="csp hash report body">subresourceURL</dfn>,
<dfn for="csp hash report body">hash</dfn>,
<dfn for="csp hash report body">type</dfn>.

<div class="example">
When a document's response contains the headers:
```http
Reporting-Endpoints: hashes-endpoint="https://example.com/reports"
Content-Security-Policy: script-src 'self' 'report-sha256'; report-to hashes-endpoint
```
and the document loads the script "main.js", a report similar to the following one will be sent:
```http
POST /reports HTTP/1.1
Host: example.com
...
Content-Type: application/reports+json

[{
"type": "csp-hash-report",
"age": 12,
"url": "https://example.com/",
"user_agent": "Mozilla/5.0 (X11; Linux i686; rv:132.0) Gecko/20100101 Firefox/132.0",
yoavweiss marked this conversation as resolved.
Show resolved Hide resolved
"body": {
"document_url": "https://example.com/",
"subresource_url": "https://example.com/main.js",
"hash": "sha256-badbeef",
"type": "subresource"
}
}]
```
</div>
<h3 id="violation-events">
Violation DOM Events
</h3>
Expand Down Expand Up @@ -3724,6 +3814,7 @@ this algorithm returns normally if compilation is allowed, and throws a
|response|, |request|, |directive|'s <a for="directive">value</a>,
and |policy|, is "`Does Not Match`", return "`Blocked`".

5. Call [=potentially report hash=] with |response|, |request|, |directive| and |policy|.
antosart marked this conversation as resolved.
Show resolved Hide resolved
2. Return "`Allowed`".

<h4 id="matching-urls">URL Matching</h4>
Expand Down