@@ -705,6 +705,8 @@ spec:SRI; urlPrefix: https://w3c.github.io/webappsec-subresource-integrity
705705 <dfn>base64-value</dfn> = 1*( <a>ALPHA</a> / <a>DIGIT</a> / "+" / "/" / "-" / "_" )*2( "=" )
706706
707707 ; Digests: 'sha256-[digest goes here]'
708+ <dfn>url-hash-source</dfn> = "'url-" <a>hash-algorithm</a> "-" <a>base64-value</a> "' "
709+ <dfn>eval-hash-source</dfn> = "'eval-" <a>hash-algorithm</a> "-" <a>base64-value</a> "' "
708710 <dfn>hash-source</dfn> = "'" <a>hash-algorithm</a> "-" <a>base64-value</a> "' "
709711 <dfn>hash-algorithm</dfn> = "sha256" / "sha384" / "sha512"
710712 </pre>
@@ -1546,8 +1548,13 @@ spec:SRI; urlPrefix: https://w3c.github.io/webappsec-subresource-integrity
15461548 [=ASCII case-insensitive=] match for the string "<a grammar>`'trusted-types-eval'`</a> ", then skip the
15471549 following steps.
15481550
1549- 1. If |source-list| contains a [=source expression=] which is an [=ASCII case-insensitive=] match for the
1550- string "<a grammar>`'unsafe-eval'`</a> ", then skip the following steps.
1551+ 1. If the result of executing [[#match-eval-hash-to-source-list]] on |source-list| and |sourceString|
1552+ is "`Matches`", then skip the following steps.
1553+
1554+ 1. If |source-list| does not contain a [=source expression=] that is a match for the
1555+ "<a grammar>`'eval-hash-source'`</a> " grammar and |source-list| contains a [=source expression=] which is an
1556+ [=ASCII case-insensitive=] match for the string "<a grammar>`'unsafe-eval'`</a> ", then skip the
1557+ following steps.
15511558
15521559 1. Let |violation| be the result of executing [[#create-violation-for-global]] on
15531560 |global|, |policy|, and "`script-src`".
@@ -3771,7 +3778,11 @@ Content-Type: application/reports+json
37713778 for="request"> integrity metadata</a> and this directive's <a
37723779 for="directive"> value</a> is "`Matches`", return "`Allowed`".
37733780
3774- 3. If |directive|'s <a for="directive">value</a> contains a <a>source
3781+ 3. If the result of executing [[#match-url-hash-to-source-list]] on
3782+ this directive's <a for="directive">value</a> and |request|'s
3783+ <a for="request">current url</a> is "`Matches`", return "`Allowed`".
3784+
3785+ 4. If |directive|'s <a for="directive">value</a> contains a <a>source
37753786 expression</a> that is an <a>ASCII case-insensitive</a> match for
37763787 the "<a grammar>`'strict-dynamic'`</a> " <a grammar>keyword-source</a> :
37773788
@@ -3783,9 +3794,13 @@ Content-Type: application/reports+json
37833794 Note: "<a grammar>`'strict-dynamic'`</a> " is explained in more detail
37843795 in [[#strict-dynamic-usage]] .
37853796
3786- 4. If the result of executing [[#match-request-to-source-list]] on
3787- |request|, |directive|'s <a for="directive">value</a> , and |policy|,
3788- is "`Does Not Match`", return "`Blocked`".
3797+ 5. If |directive|'s <a for="directive">value</a> does not contain a
3798+ <a>source expression</a> that is a match for the
3799+ "<a grammar>`'url-hash-source'`</a> " grammar:
3800+
3801+ 1. If the result of executing [[#match-request-to-source-list]] on
3802+ |request|, |directive|'s <a for="directive">value</a> , and
3803+ |policy|, is "`Does Not Match`", return "`Blocked`".
37893804
37903805 2. Return "`Allowed`".
37913806
@@ -4404,53 +4419,104 @@ Content-Type: application/reports+json
44044419 set |unsafe-hashes flag| to `true`. Break out of the loop.
44054420
44064421 5. If |type| is "`script`" or "`style`", or |unsafe-hashes flag| is
4407- `true`:
4422+ `true`, return result of executing [[#match-value-hash-to-source-list]] on
4423+ |source|, "`content`" and |list|.
44084424
4409- 1. Set |source| to the result of executing <a>UTF-8 encode</a>
4410- on the result of executing <a for="JavaScript string" data-lt="convert">JavaScript string converting</a>
4411- on |source|.
4425+ Note: Hashes apply to inline <{script}> and inline <{style}> . If the
4426+ "<a grammar>`'unsafe-hashes'`</a> " source expression is present,
4427+ they will also apply to event handlers, style attributes and `javascript:`
4428+ navigations.
44124429
4413- 2. <a for=set>For each</a> |expression| of |list|:
4430+ ISSUE(w3c/webappsec-csp#426): This should handle ` 'strict-dynamic' ` for dynamically inserted inline scripts.
44144431
4415- 1 . If |expression| matches the <a grammar>`hash-source`</a> grammar:
4432+ 6 . Return "`Does Not Match`".
44164433
4417- 1. Let |algorithm| be null.
4434+ <h5 id="match-url-hash-to-source-list" algorithm>
4435+ Does the hash of |url| match |source list|?
4436+ </h5>
44184437
4419- 2. If |expression|'s <a grammar>`hash-algorithm`</a> part is an
4420- <a>ASCII case-insensitive</a> match for "sha256", set
4421- |algorithm| to <a>SHA-256</a> .
4438+ Given a <a>source list</a> |source list| and a url |url|, this algorithm
4439+ returns "`Matches`" or "`Does Not Match`".
44224440
4423- 3 . If |expression|'s <a grammar>`hash-algorithm`</a> part is an
4424- <a>ASCII case-insensitive</a> match for "sha384", set
4425- |algorithm| to <a>SHA-384</a> .
4441+ 1 . Return the result of executing
4442+ [[#match-value-hash-to-source-list]] on |url|'s {{URL/href}} ,
4443+ "`url-hash`", and |source list| .
44264444
4427- 4. If |expression|'s <a grammar>` hash-algorithm`</a> part is an
4428- <a>ASCII case-insensitive</a> match for "sha512", set
4429- |algorithm| to <a>SHA-512</a> .
4445+ <h5 id="match-eval- hash-to-source-list" algorithm>
4446+ Does the hash of |sourceString| match |source list|?
4447+ </h5>
44304448
4431- 5. If |algorithm| is not null:
4449+ Given a <a>source list</a> |source list| and a source string |sourceString|,
4450+ this algorithm returns "`Matches`" or "`Does Not Match`".
44324451
4433- 1. Let |actual| be the result of <a>base64 encoding</a> the
4434- result of applying |algorithm| to |source|.
4452+ 1. Return the result of executing
4453+ [[#match-value-hash-to-source-list]] on |sourceString|, "`eval-hash`",
4454+ and |source list|.
44354455
4436- 2. Let |expected| be |expression|'s <a grammar>`base64-value`</a> part,
4437- with all '`-`' characters replaced with '`+`' , and all '`_`' characters
4438- replaced with '`/`' .
4456+ <h5 id="is-expression-of-hash-type" algorithm>
4457+ Is |expression| of |hash type|?
4458+ </h5>
44394459
4440- Note: This replacement normalizes hashes expressed in [=base64url
4441- encoding=] into [=base64 encoding=] for matching .
4460+ Given a {{String}} |hash type| and a <a grammar>source-expression</a>
4461+ |expression|, this algorithm returns "`Yes`" or "`No`" .
44424462
4443- 3 . If |actual | is <a for="string" lt="is">identical to</a>
4444- |expected| , return "`Matches `".
4463+ 1 . If |hash type | is "url-hash" and |expression| matches the
4464+ <a grammar>`url-hash-source`</a> grammar , return "`Yes `".
44454465
4446- Note: Hashes apply to inline <{script}> and inline <{style}> . If the
4447- "<a grammar>`'unsafe-hashes'`</a> " source expression is present,
4448- they will also apply to event handlers, style attributes and `javascript:`
4449- navigations.
4466+ 2. If |hash type| is "eval-hash" and |expression| matches the
4467+ <a grammar>`eval-hash-source`</a> grammar, return "`Yes`".
44504468
4451- ISSUE(w3c/webappsec-csp#426): This should handle `'strict-dynamic' ` for dynamically inserted inline scripts.
4469+ 3. If |expression| matches the <a grammar>`hash-source`</a> grammar,
4470+ return "`Yes`".
44524471
4453- 6. Return "`Does Not Match`".
4472+ 4. Return "`No`".
4473+
4474+ <h5 id="match-value-hash-to-source-list" algorithm>
4475+ Does the hash of |value| match |source list|?
4476+ </h5>
4477+
4478+ Given a {{String}} |value|, {{String}} |hash type|, and a <a>source list</a>
4479+ |source list| type , this algorithm returns "`Matches`" or "`Does Not Match`".
4480+
4481+ 1. Set |value| to the result of executing <a>UTF-8 encode</a>
4482+ on the result of executing <a for="JavaScript string" data-lt="convert">JavaScript string converting</a>
4483+ on |value|.
4484+
4485+ 2. <a for=set>For each</a> |expression| of |source list|:
4486+
4487+ 1. If the result of executing [[#is-expression-of-hash-type]] with
4488+ |hash type| and |expression| is "`Yes`":
4489+
4490+ 1. Let |algorithm| be null.
4491+
4492+ 2. If |expression|'s <a grammar>`hash-algorithm`</a> part is an
4493+ <a>ASCII case-insensitive</a> match for "sha256", set
4494+ |algorithm| to <a>SHA-256</a> .
4495+
4496+ 3. If |expression|'s <a grammar>`hash-algorithm`</a> part is an
4497+ <a>ASCII case-insensitive</a> match for "sha384", set
4498+ |algorithm| to <a>SHA-384</a> .
4499+
4500+ 4. If |expression|'s <a grammar>`hash-algorithm`</a> part is an
4501+ <a>ASCII case-insensitive</a> match for "sha512", set
4502+ |algorithm| to <a>SHA-512</a> .
4503+
4504+ 5. If |algorithm| is not null:
4505+
4506+ 1. Let |actual| be the result of <a>base64 encoding</a> the
4507+ result of applying |algorithm| to |value|.
4508+
4509+ 2. Let |expected| be |expression|'s <a grammar>`base64-value`</a> part,
4510+ with all '`-`' characters replaced with '`+`' , and all '`_`' characters
4511+ replaced with '`/`' .
4512+
4513+ Note: This replacement normalizes hashes expressed in [=base64url
4514+ encoding=] into [=base64 encoding=] for matching.
4515+
4516+ 3. If |actual| is <a for="string" lt="is">identical to</a>
4517+ |expected|, return "`Matches`".
4518+
4519+ 3. Return "`Does Not Match`".
44544520
44554521 <h3 id="directive-algorithms">Directive Algorithms</h3>
44564522
0 commit comments