Skip to content

Commit 58691e0

Browse files
authored
Adapt to the policy container (#482)
This change adapts the CSP spec to the concept of the policy container, which was just introduced in html (whatwg/html#6504). The main changes are: - the CSP list is now part of the policy container of a Document/WorkerGlobalScope/WorkletGlobalScope, and not directly owned by it anymore, - inheritance of CSP for local scheme documents is now taken care by the html spec as part of the policy container inheritance.
1 parent 65f7dc3 commit 58691e0

File tree

1 file changed

+84
-155
lines changed

1 file changed

+84
-155
lines changed

index.bs

Lines changed: 84 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,13 @@ spec: SHA2; urlPrefix: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pd
128128

129129
spec: HTML; urlPrefix: https://html.spec.whatwg.org/
130130
type: dfn
131-
for: WorkerGlobalScope
132-
text: owner set; url: concept-WorkerGlobalScope-owner-set
133-
text: process the iframe attributes; url: process-the-iframe-attributes
134131
for: script
135132
text: "parser-inserted"
136133
text: origin; url: concept-origin
137134
text: browsing context; url: browsing-context
138135
text: content security policy state; url: attr-meta-http-equiv-content-security-policy
139136
text: create and initialize a new document object; url: initialise-the-document-object
137+
text: initializing a new Document object; url: initialise-the-document-object
140138

141139
spec: INFRA; urlPrefix: https://infra.spec.whatwg.org/
142140
type: grammar
@@ -396,8 +394,7 @@ spec: INFRA; urlPrefix: https://infra.spec.whatwg.org/
396394

397395
A <dfn export lt="content security policy object" local-lt="policy">policy</dfn> defines allowed
398396
and restricted behaviors, and may be applied to a {{Document}}, {{WorkerGlobalScope}}, or
399-
{{WorkletGlobalScope}} as described in [[#initialize-global-object-csp]] and in
400-
[[#initialize-document-csp]].
397+
{{WorkletGlobalScope}}.
401398

402399
Each policy has an associated <dfn for="policy" export>directive set</dfn>, which is an <a>ordered
403400
set</a> of <a>directives</a> that define the policy's implications when applied.
@@ -415,8 +412,6 @@ spec: INFRA; urlPrefix: https://infra.spec.whatwg.org/
415412
<a>local scheme</a> documents/workers that have inherited their policy but
416413
have an <a>opaque origin</a>. Most of the time this will simply be the
417414
<a>environment settings object</a>'s [=environment settings object/origin=].
418-
The [[#initialize-document-csp]] algorithm describes situations in which
419-
a policy is inherited.
420415

421416
Multiple [=/policies=] can be applied to a single resource, and are collected into a [=list=] of
422417
[=/policies=] known as a <dfn export>CSP list</dfn>.
@@ -521,6 +516,38 @@ spec: INFRA; urlPrefix: https://infra.spec.whatwg.org/
521516
4. Return |policies|.
522517
</ol>
523518

519+
<h4 id="parse-response-csp" algorithm dfn export>
520+
Parse |response|'s Content Security Policies
521+
</h4>
522+
523+
To <dfn abstract-op>parse a response's Content Security Policies</dfn> given a <a>response</a>
524+
(|response|):
525+
526+
<ol class="algorithm">
527+
1. Let |policies| be the result of <a abstract-op lt="parse a serialized CSP list">parsing</a>
528+
the result of [=extracting header list values=] given `Content-Security-Policy` and
529+
|response|'s [=response/header list=], with a [=policy/source=] of "`header`", and a
530+
[=policy/disposition=] of "`enforce`".
531+
532+
2. Append to |policies| the result of
533+
<a abstract-op lt="parse a serialized CSP list">parsing</a> the result of
534+
[=extracting header list values=] given `Content-Security-Policy-Report-Only` and
535+
|response|'s [=response/header list=], with a [=policy/source=] of "`header`", and a
536+
[=policy/disposition=] of "`report`".
537+
538+
3. For each |policy| in |policies|:
539+
540+
1. Set |policy|'s [=policy/self-origin=] to |response|'s [=response/url=]'s
541+
[=url/origin=].
542+
543+
4. Return |policies|.
544+
</ol>
545+
546+
Note: When <a abstract-op lt="parse a response's Content Security Policies">parsing a response's
547+
Content Security Policies</a>, if the resulting |policies| end up containing at least one item,
548+
user agents can hold a flag on |policies| and use it to optimize away the [=/contains a
549+
header-delivered Content Security Policy=] algorithm.
550+
524551
<h3 id="framework-directives">Directives</h3>
525552

526553
Each <a for="/">policy</a> contains an <a>ordered set</a> of <dfn export>directives</dfn> (its
@@ -571,9 +598,9 @@ spec: INFRA; urlPrefix: https://infra.spec.whatwg.org/
571598
algorithm returns "`Allowed`" unless otherwise specified.
572599

573600
5. An <dfn for="directive" export>initialization</dfn>, which takes a {{Document}}
574-
or <a for="/">global object</a>, a <a>response</a>, and a <a for="/">policy</a>
575-
as arguments. This algorithm is executed during [[#initialize-document-csp]],
576-
and has no effect unless otherwise specified.
601+
or <a for="/">global object</a> and a <a for="/">policy</a> as arguments. This
602+
algorithm is executed during [[#run-document-csp-initialization]], and has no
603+
effect unless otherwise specified.
577604

578605
6. A <dfn for="directive" export>pre-navigation check</dfn>, which takes a
579606
<a for="/">request</a>, a navigation type string ("`form-submission`"
@@ -1000,25 +1027,9 @@ spec: INFRA; urlPrefix: https://infra.spec.whatwg.org/
10001027
populates its <a for="response">CSP list</a> accordingly:
10011028

10021029
<ol class="algorithm">
1003-
1. Set |response|'s [=response/CSP list=] to the empty list.
1004-
1005-
2. Let |policies| be the result of <a abstract-op lt="parse a serialized CSP list">parsing</a>
1006-
the result of [=extracting header list values=] given `Content-Security-Policy` and
1007-
|response|'s [=response/header list=], with a [=policy/source=] of "`header`", and a
1008-
[=policy/disposition=] of "`enforce`".
1009-
1010-
3. Append to |policies| the result of
1011-
<a abstract-op lt="parse a serialized CSP list">parsing</a> the result of
1012-
[=extracting header list values=] given `Content-Security-Policy-Report-Only` and
1013-
|response|'s [=response/header list=], with a [=policy/source=] of "`header`", and a
1014-
[=policy/disposition=] of "`report`".
1015-
1016-
4. For each |policy| in |policies|:
1017-
1018-
1. Set |policy|'s [=policy/self-origin=] to |response|'s [=response/url=]'s
1019-
[=url/origin=].
1020-
1021-
2. Insert |policy| into |response|'s <a for="response">CSP list</a>.
1030+
1. Set |response|'s [=response/CSP list=] to the result of <a abstract-op
1031+
lt="parse a response's Content Security Policies">parsing</a> |response|'s
1032+
Content Security Policies.
10221033
</ol>
10231034

10241035
<h4 id="report-for-request" algorithm dfn export>
@@ -1131,11 +1142,11 @@ spec: INFRA; urlPrefix: https://infra.spec.whatwg.org/
11311142
Integration with HTML
11321143
</h3>
11331144

1134-
1. The {{Document}}, {{WorkerGlobalScope}}, and {{WorkletGlobalScope}} objects have a
1135-
`CSP list`, which holds all the <a for="/">policy</a> objects which are
1136-
active for a given context. This list is empty unless otherwise specified,
1137-
and is populated via the [[#initialize-global-object-csp]] and
1138-
[[#initialize-document-csp]] algorithms.
1145+
1. The [=/policy container=] has a [=policy container/CSP list=], which holds
1146+
all the <a for="/">policy</a> objects which are active for a given context. This
1147+
list is empty unless otherwise specified, and is populated from the <a>response</a> by <a
1148+
abstract-op lt="parse a response's Content Security Policies">parsing</a> <a>response</a>'s
1149+
Content Security Policies or inherited following the rules of the [=/policy container=].
11391150

11401151
2. A <a for="/">global object</a>'s <dfn for="global object" id="global-object-csp-list">CSP list</dfn>
11411152
is the result of executing [[#get-csp-of-object]] with the <a for="/">global object</a>
@@ -1145,146 +1156,66 @@ spec: INFRA; urlPrefix: https://infra.spec.whatwg.org/
11451156
<a for="/">global object</a> by inserting it into the <a for="/">global object</a>'s
11461157
<a for="global object">CSP list</a>.
11471158

1148-
4. [[#initialize-global-object-csp]] is called during the <a>run a worker</a>
1149-
algorithm in order to bind a set of <a for="/">policy</a> objects associated
1150-
with a <a>response</a> {{WorkerGlobalScope}} or {{WorkletGlobalScope}}.
1151-
1152-
5. [[#initialize-document-csp]] is called during the <a>create and initialize a
1153-
new `Document` object</a> algorithm in order to bind a set of <a for="/">policy</a>
1154-
objects associated with a <a>response</a> to a newly created {{Document}}.
1159+
4. [[#run-document-csp-initialization]] is called during the <a>create and initialize a
1160+
new `Document` object</a> algorithm.
11551161

1156-
6. [[#should-block-inline]] is called during the <a>prepare a script</a> and
1162+
5. [[#should-block-inline]] is called during the <a>prepare a script</a> and
11571163
<a>update a `style` block</a> algorithms in order to determine whether or
11581164
not an inline script or style block is allowed to execute/render.
11591165

1160-
7. [[#should-block-inline]] is called during handling of inline event
1166+
6. [[#should-block-inline]] is called during handling of inline event
11611167
handlers (like `onclick`) and inline `style` attributes in order to
11621168
determine whether or not they ought to be allowed to execute/render.
11631169

1164-
8. <a for="/">policy</a> is <a>enforced</a> during processing of the <{meta}>
1170+
7. <a for="/">policy</a> is <a>enforced</a> during processing of the <{meta}>
11651171
element's <{meta/http-equiv}>.
11661172

1167-
9. A {{Document}}'s <dfn>embedding document</dfn> is the {{Document}}'s
1168-
<a>browsing context</a>'s [=browsing context/container document=].
1169-
1170-
10. HTML populates each <a for="/">request</a>'s <a for="request">cryptographic nonce
1173+
9. HTML populates each <a for="/">request</a>'s <a for="request">cryptographic nonce
11711174
metadata</a> and <a>parser metadata</a> with relevant data from the
11721175
elements responsible for resource loading.
11731176

11741177
ISSUE(whatwg/html#968): Stylesheet loading is not yet integrated with
11751178
Fetch in WHATWG's HTML.
11761179

1177-
11. [[#allow-base-for-document]] is called during <{base}>'s <a>set the frozen
1180+
9. [[#allow-base-for-document]] is called during <{base}>'s <a>set the frozen
11781181
base URL</a> algorithm to ensure that the <{base/href}> attribute's value
11791182
is valid.
11801183

1181-
12. [[#should-block-navigation-request]] is called during the <a>process a
1184+
10. [[#should-block-navigation-request]] is called during the <a>process a
11821185
navigate fetch</a> algorithm, and [[#should-block-navigation-response]]
11831186
is called during the <a>process a navigate response</a> algorithm to
11841187
apply directive's navigation checks, as well as inline checks for
11851188
navigations to `javascript:` URLs.
11861189

1187-
<h4 id="initialize-document-csp" algorithm dfn export>
1188-
Initialize a `Document`'s `CSP list`
1190+
<h4 id="run-document-csp-initialization" algorithm dfn export>
1191+
Run `CSP` initialization for a `Document`
11891192
</h4>
11901193

1191-
Given a {{Document}} (|document|), a <a>response</a> (|response|), and a
1192-
<a for="/">request</a> or `null` (|request|) the user agent performs the following
1193-
steps in order to initialize |document|'s <a for="Document">CSP list</a>:
1194-
1195-
1. If |request| is not `null` and |response|'s <a for="response">url</a>'s
1196-
<a for="url">scheme</a> is either a <a>local scheme</a> or `javascript`:
1197-
1198-
1. For each |policy| in |request|'s <a for="request">client</a>'s
1199-
<a for="environment settings object">global object</a>'s
1200-
<a for="global object">CSP list</a>:
1201-
1202-
1. Insert a copy of |policy| into |document|'s
1203-
<a for="Document">CSP list</a>.
1204-
1205-
Note: For <a data-lt="an iframe srcdoc Document">iframe srcdoc Documents</a>,
1206-
|request| will be `null`, but |response| will contain a copy of the
1207-
<a>embedding document</a>'s <a for="Document">CSP list</a> in its
1208-
<a for="response">CSP list</a>, as specified in <a>process the iframe attributes</a>.
1209-
As such <a data-lt="an iframe srcdoc Document">iframe srcdoc Documents</a>
1210-
inherit their <a>embedding document</a>'s <a for="Document">CSP list</a>.
1211-
1212-
Note: Since [=policy/self-origin=] is also copied, any <a grammar>`'self'`</a>
1213-
checks will be using the <a>source browsing context</a>'s origin. This is
1214-
done for the purpose of making <a grammar>`'self'`</a> make sense in documents
1215-
with <a>opaque origins</a>. The <a grammar>`'self'`</a> keyword is used
1216-
in the [[#match-url-to-source-expression]] algorithm.
1194+
Given a {{Document}} (|document|), the user agent performs the following
1195+
steps in order to initialize CSP for |document|:
12171196

1218-
Note: We do all this to ensure that a page cannot bypass its <a for="/">policy</a>
1219-
by embedding a frame or popping up a new window containing content it
1220-
controls (`blob:` resources, or `document.write()`).
1221-
1222-
2. For each |policy| in |response|'s <a for="response">CSP list</a>, insert
1223-
|policy| into |document|'s <a for="Document">CSP list</a>.
1224-
1225-
3. For each |policy| in |document|'s <a for="Document">CSP list</a>:
1197+
1. For each |policy| in |document|'s [=Document/policy container=]'s
1198+
[=policy container/CSP list=]:
12261199

12271200
1. For each |directive| in |policy|:
12281201

12291202
1. Execute |directive|'s <a for="directive">initialization</a>
1230-
algorithm on |document| and |response|.
1231-
1232-
<h4 id="initialize-global-object-csp" algorithm dfn export>
1233-
Initialize a global object's `CSP list`
1234-
</h4>
1235-
1236-
Given a <a for="/">global object</a> (|global|), and a <a>response</a>
1237-
(|response|), the user agent performs the following steps in order
1238-
to initialize |global|'s <a for="global object">CSP list</a>:
1239-
1240-
1. If |response|'s <a for="response">url</a>'s <a for="url">scheme</a> is a
1241-
<a>local scheme</a>, or if |global| is a {{DedicatedWorkerGlobalScope}}:
1242-
1243-
1. Let |owners| be an empty list.
1244-
1245-
2. Add each of the items in |global|'s [=WorkerGlobalScope/owner set=] to |owners|.
1246-
1247-
4. For each |owner| in |owners|:
1248-
1249-
1. For each |policy| in |owner|'s <a for="global object">CSP list</a>:
1250-
1251-
1. Insert a copy of |policy| into |global|'s
1252-
<a for="global object">CSP list</a>.
1253-
1254-
Note: <a>local scheme</a> includes `about:`, and this algorithm will
1255-
therefore copy the <a>embedding document</a>'s policies for <a>an iframe
1256-
`srcdoc` `Document`</a>.
1257-
1258-
2. If |global| is a {{SharedWorkerGlobalScope}} or {{ServiceWorkerGlobalScope}}:
1259-
1260-
1. For each |policy| in |response|'s
1261-
<a for="response">CSP list</a>, insert |policy| into
1262-
|global|'s <a for="global object">CSP list</a>.
1263-
1264-
3. If |global| is a {{WorkletGlobalScope}}:
1265-
1266-
1. Let |owner| be |global|'s [=WorkletGlobalScope/owner document=].
1267-
1268-
2. For each |policy| in |owner|'s <a for="global object">CSP list</a>:
1269-
1270-
1. Insert a copy of |policy| into |global|'s <a for="global object">CSP list</a>.
1203+
algorithm on |document|.
12711204

12721205
<h4 id="get-csp-of-object" algorithm>
12731206
Retrieve the <a for="global object">CSP list</a> of an |object|
12741207
</h4>
12751208

12761209
To obtain |object|'s <a for="global object">CSP list</a>:
12771210

1278-
1. If |object| is a {{Document}} return |object|'s <a for="Document">CSP list</a>.
1279-
1280-
2. If |object| is a {{Window}} return |object|'s <a>associated `Document`</a>'s
1281-
<a for="Document">CSP list</a>.
1282-
1283-
3. If |object| is a {{WorkerGlobalScope}}, return |object|'s <a for="global object">CSP list</a>.
1211+
1. If |object| is a {{Document}} return |object|'s [=Document/policy container=]'s
1212+
[=policy container/CSP list=].
12841213

1285-
4. If |object| is a {{WorkletGlobalScope}}, return |object|'s <a for="global object">CSP list</a>.
1214+
2. If |object| is a {{Window}} or a {{WorkerGlobalScope}} or a {{WorkletGlobalScope}},
1215+
return <a>environment settings object</a>'s [=environment settings object/policy
1216+
container=]'s [=policy container/CSP list=].
12861217

1287-
5. Return `null`.
1218+
3. Return `null`.
12881219

12891220
<h4 id="should-block-inline" algorithm dfn export>
12901221
Should |element|'s inline |type| behavior be blocked by Content Security Policy?
@@ -1410,17 +1341,16 @@ spec: INFRA; urlPrefix: https://infra.spec.whatwg.org/
14101341
in |target| be blocked by Content Security Policy?
14111342
</h4>
14121343

1413-
Given a <a for="/">request</a> (|navigation request|), a string (|type|, either
1414-
"`form-submission`" or "`other`"), a <a>response</a> |navigation
1415-
response|, and a <a>browsing context</a> |target|, this algorithm
1344+
Given a <a for="/">request</a> (|navigation request|), a <a>response</a> |navigation
1345+
response|, a [=/CSP list=] |response CSP list|, a string (|type|, either
1346+
"`form-submission`" or "`other`"), and a <a>browsing context</a> |target|, this algorithm
14161347
returns "`Blocked`" if the active policy blocks the navigation, and "`Allowed`"
14171348
otherwise:
14181349

14191350
<ol class="algorithm">
14201351
1. Let |result| be "`Allowed`".
14211352

1422-
2. For each |policy| in |navigation response|'s
1423-
<a for="response">CSP list</a>:
1353+
2. For each |policy| in |response CSP list|:
14241354

14251355
Note: Some directives (like <a>frame-ancestors</a>) allow a |response|'s
14261356
<a>Content Security Policy</a> to act on the navigation.
@@ -3427,18 +3357,16 @@ spec: INFRA; urlPrefix: https://infra.spec.whatwg.org/
34273357
according to the <a>`sandbox`</a> values present in its policies, as
34283358
follows:
34293359

3430-
Given a {{Document}} or <a for="/">global object</a> (|context|), a <a>response</a>
3431-
(|response|), and a <a for="/">policy</a> (|policy|):
3360+
Given a {{Document}} or <a for="/">global object</a> (|context|) and a <a for="/">policy</a>
3361+
(|policy|):
34323362

3433-
1. Assert: |response| is unused.
3434-
3435-
2. If |policy|'s <a for="policy">disposition</a> is not "`enforce`", or
3363+
1. If |policy|'s <a for="policy">disposition</a> is not "`enforce`", or
34363364
|context| is not a {{Document}}, then abort this algorithm.
34373365

34383366
Note: This will need to change if we allow Workers to be sandboxed,
34393367
which seems like a pretty reasonable thing to do.
34403368

3441-
3. <a>Parse a sandboxing directive</a> using this directive's
3369+
2. <a>Parse a sandboxing directive</a> using this directive's
34423370
<a for="directive">value</a> as the input, and |context|'s <a>forced
34433371
sandboxing flag set</a> as the output.
34443372

@@ -3517,21 +3445,23 @@ spec: INFRA; urlPrefix: https://infra.spec.whatwg.org/
35173445
`frame-ancestors` directive's <a>navigation response check</a>:
35183446

35193447
<ol class="algorithm">
3520-
1. Assert: |request|, |navigation response|, and |navigation type|, are
3521-
unused in this algorithm, as `frame-ancestors` is concerned only
3448+
1. If |navigation response|'s [=response/URL=] [=is local=], return "`Allowed`".
3449+
3450+
2. Assert: |request|, |navigation response|, and |navigation type|, are unused
3451+
from this point forward in this algorithm, as `frame-ancestors` is concerned only
35223452
with |navigation response|'s <a>frame-ancestors</a> <a>directive</a>.
35233453

3524-
2. If |check type| is "`source`", return "`Allowed`".
3454+
3. If |check type| is "`source`", return "`Allowed`".
35253455

35263456
Note: The 'frame-ancestors' <a>directive</a> is relevant only to the
35273457
|target| <a>browsing context</a> and it has no impact on the |request|'s
35283458
context.
35293459

3530-
2. If |target| is not a <a>nested browsing context</a>, return "`Allowed`".
3460+
4. If |target| is not a <a>nested browsing context</a>, return "`Allowed`".
35313461

3532-
3. Let |current| be |target|.
3462+
5. Let |current| be |target|.
35333463

3534-
4. While |current| is a <a>nested browsing context</a>:
3464+
6. While |current| is a <a>nested browsing context</a>:
35353465

35363466
1. Let |document| be |current|'s [=browsing context/container document=].
35373467

@@ -3545,7 +3475,7 @@ spec: INFRA; urlPrefix: https://infra.spec.whatwg.org/
35453475

35463476
4. Set |current| to |document|'s <a>browsing context</a>.
35473477

3548-
5. Return "`Allowed`".
3478+
7. Return "`Allowed`".
35493479
</ol>
35503480

35513481
<h5 id="frame-ancestors-and-frame-options">
@@ -4751,8 +4681,7 @@ spec: INFRA; urlPrefix: https://infra.spec.whatwg.org/
47514681
CSP Inheriting to avoid bypasses
47524682
</h3>
47534683

4754-
As described in [[#initialize-document-csp]] and [[#initialize-global-object-csp]],
4755-
documents loaded from <a>local schemes</a> will inherit a copy of the
4684+
Documents loaded from <a>local schemes</a> will inherit a copy of the
47564685
policies in the <a>source browsing context</a>. The goal is to ensure that a page can't
47574686
bypass its policy by embedding a frame or opening a new window containing
47584687
content that is entirely under its control (`srcdoc` documents, `blob:` or `data:`

0 commit comments

Comments
 (0)