@@ -14,15 +14,21 @@ Boilerplate: omit conformance
14
14
Markup Shorthands : css off, markdown on
15
15
</pre>
16
16
<pre class="anchors">
17
- urlPrefix: https://html.spec.whatwg.org/; spec: HTML; type: dfn
18
- text: origin; url: multipage/origin.html#concept-origin
19
- text: cross-origin opener policy; url: multipage/origin.html#cross-origin-opener-policies
20
- text: cross-origin embedder policy; url: multipage/origin.html#coep
17
+ urlPrefix: https://html.spec.whatwg.org/; spec: HTML;
18
+ type: dfn
19
+ text: origin; url: multipage/origin.html#concept-origin
20
+ text: cross-origin opener policy; url: multipage/origin.html#cross-origin-opener-policies
21
+ text: cross-origin embedder policy; url: multipage/origin.html#coep
22
+ type: http-header
23
+ text: cross-origin-opener-policy; url: multipage/origin.html#cross-origin-opener-policies
24
+ text: x-frame-options; url: multipage/browsing-the-web.html#the-x-frame-options-header
21
25
urlPrefix: https://fetch.spec.whatwg.org/; spec: FETCH; type: dfn
22
26
text: cross-origin resource policy; url: #http-cross-origin-resource-policy
23
27
text: cross-origin read blocking; url: #corb
24
28
urlPrefix: https://tc39.es/ecma262/; spec: ECMA262; type: interface
25
29
text: SharedArrayBuffer; url: #sec-sharedarraybuffer-objects
30
+ urlPrefix: https://tools.ietf.org/html/rfc7231; spec: RFC7231; type: http-header
31
+ text: Vary; url: #section-7.1.4
26
32
</pre>
27
33
<pre class="biblio">
28
34
{
@@ -248,6 +254,57 @@ Practical Examples {#examples}
248
254
Subresources {#subresources}
249
255
----------------------------
250
256
257
+ Resources which are intended to be loaded into documents should protect themselves from being used
258
+ in unexpected ways. Before walking through strategies for specific kinds of resources, a few headers
259
+ seem generally applicable:
260
+
261
+ 1. Sites should use Fetch Metadata to make good decisions about when to serve resources, as
262
+ described in [[resource-isolation-policy]] . In order to ensure that decision sticks, servers
263
+ should explain its decision to the browser by sending a <a http-header>`Vary`</a> header
264
+ containing `Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site`. This ensures that the server has
265
+ a chance to make different decisions for requests which will be *used* differently.
266
+
267
+ 2. Subresources should opt-out of MIME type sniffing by sending an
268
+ <a http-header>`X-Content-Type-Options`</a> header with a value of `nosniff`. This increases the
269
+ robustness of MIME-based checks like [=cross-origin read blocking=] (CORB) /
270
+ <a href="https://github.com/annevk/orb">opaque response blocking</a> ([[ORB]] ), and mitigates
271
+ some well-known risks around type confusion for scripts.
272
+
273
+ 3. Subresources are intended for inclusion in a given context, not as independently navigable
274
+ documents. To mitigate the risk that navigation to a subresource causes script execution or
275
+ opens an origin up to attack in some other way, servers can assert the following set of headers
276
+ which collectively make it difficult to meaningfully abuse a subresource via navigation:
277
+
278
+ * Using the <a http-header>`Content-Security-Policy`</a> header's to assert the
279
+ <a>`sandbox`</a> directive ensures that these resources remain inactive if navigated to
280
+ directly as a top-level document. No scripts will execute, and the resource will be pushed
281
+ into an [=opaque origin=] .
282
+
283
+ Note: Some servers deliver `Content-Disposition: attachment; filename=file.name` to obtain
284
+ a similar effect. This was valuable to mitigate vulnerabilies in Flash, but the sandbox
285
+ approach seems to more straightforwardly address the threats we care about today.
286
+
287
+ * Asserting the <a http-header>`Cross-Origin-Opener-Policy`</a> header with a value of
288
+ `same-origin` prevents cross-origin documents from retaining a handle to the resource's
289
+ window if it's opened in a popup.
290
+
291
+ * The <a http-header>`X-Frame-Options`</a> header with a value of `DENY` prevents the resource
292
+ from being framed.
293
+
294
+ Most subresources, then, should contain the following block of headers, which you'll see repeated a
295
+ few times below:
296
+
297
+ <pre highlight="http">
298
+ Content-Security-Policy: sandbox
299
+ Cross-Origin-Opener-Policy: same-origin
300
+ Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site
301
+ X-Content-Type-Options: nosniff
302
+ X-Frame-Options: DENY
303
+ </pre>
304
+
305
+ With these generic protections in mind, let's sift through a few scenarios to determine what headers
306
+ a server would be well-served to assert:
307
+
251
308
### Static Subresources ### {#static-subresources}
252
309
253
310
By their nature, static resources contain the same data no matter who requests them, and therefore
@@ -256,16 +313,16 @@ to making these resources widely available, and value in allowing embedders to r
256
313
something like the following response headers could be appropriate:
257
314
258
315
<pre highlight="http">
259
- Access-Control-Allow-Origin: *
316
+ <strong> Access-Control-Allow-Origin: *
260
317
Cross-Origin-Resource-Policy: cross-origin
261
- Timing-Allow-Origin: *
318
+ Timing-Allow-Origin: *</strong>
319
+ Content-Security-Policy: sandbox
320
+ Cross-Origin-Opener-Policy: same-origin
321
+ Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site
262
322
X-Content-Type-Options: nosniff
323
+ X-Frame-Options: DENY
263
324
</pre>
264
325
265
- (Given these resources' characteristics, there's little risk in allowing them to be embedded in
266
- frames, but likely also little value. Unless there's a good reason to allow framing these
267
- subresources directly, consider also adding `X-Frame-Options: DENY`).
268
-
269
326
CDNs are the canonical static resource distribution points, and many use the pattern above. Take
270
327
a look at the following common resources' response headers for inspiration:
271
328
@@ -287,26 +344,21 @@ in question. A few cases are well worth considering:
287
344
288
345
1. Application-internal resources (private API endpoints, avatar images, uploaded data, etc.)
289
346
should not be available to any cross-origin requestor. These resources should be restricted to
290
- usage as a subresource in same-origin contexts by sending the following headers:
347
+ usage as a subresource in same-origin contexts by sending a
348
+ <a http-header>`Cross-Origin-Resource-Policy`</a> header with a value of `same-origin`:
291
349
292
- <pre class="lang-http">
350
+ <pre highlight="http">
351
+ <strong> Cross-Origin-Resource-Policy: same-origin</strong>
352
+ Content-Security-Policy: sandbox
293
353
Cross-Origin-Opener-Policy: same-origin
294
- Cross-Origin-Resource-Policy: same-origin
295
- Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site
296
- X-Content-Type-Options: nosniff
297
- X-Frame-Options: DENY
298
- Content-Disposition: attachment; filename=file.name
354
+ Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site
355
+ X-Content-Type-Options: nosniff
356
+ X-Frame-Options: DENY
299
357
</pre>
300
358
301
- The most critical of these headers is `Cross-Origin-Resource-Policy: same-origin`, which will
302
- prevent attackers from loading this as a `no-cors` subresource in a cross-origin document.
303
- `X-Frame-Options` and `Cross-Origin-Opener-Policy` further restrict attackers' ability to frame
304
- this subresource, or open it in a window they might retain access to. `Content-Disposition`
305
- prevents some browsers from commiting this file as a document at all, prompting instead for
306
- permission to download the contents.
359
+ This header will prevent cross-origin attackers from loading the resource as a response to a
360
+ `no-cors` request.
307
361
308
- ISSUE(mikewest/post-spectre-webdev#1): Does `Content-Disposition` make any sense?
309
-
310
362
For example, examine the headers returned when requesting endpoints like the following:
311
363
312
364
* <a href="https://myaccount.google.com/_/AccountSettingsUi/browserinfo">`https://myaccount.google.com/_/AccountSettingsUi/browserinfo`</a>
@@ -318,23 +370,24 @@ in question. A few cases are well worth considering:
318
370
safely be enabled by requiring CORS, and choosing the set of origins for which a given response
319
371
can be exposed by setting the appropriate access-control headers, for example:
320
372
321
- <pre class="lang- http">
322
- Access-Control-Allow-Credentials: true
373
+ <pre highlight=" http">
374
+ <strong> Access-Control-Allow-Credentials: true
323
375
Access-Control-Allow-Origin: https://trusted.example
324
376
Access-Control-Allow-Methods: POST
325
377
Access-Control-Allow-Headers: ...
326
378
Access-Control-Allow-...: ...
379
+ Cross-Origin-Resource-Policy: same-origin</strong>
380
+ Content-Security-Policy: sandbox
327
381
Cross-Origin-Opener-Policy: same-origin
328
- Cross-Origin-Resource-Policy: same-origin
329
382
Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site
330
383
X-Content-Type-Options: nosniff
331
384
X-Frame-Options: DENY
332
385
</pre>
333
386
334
387
Note: The `Cross-Origin-Resource-Policy` header is only processed for requests that are _not_
335
388
using CORS for access control ("`no-cors` requests"). Sending
336
- `Cross-Origin-Resource-Policy: same-origin` is therefore not harmful, and working as a solid
337
- belts-and-suspenders approach to ensuring that `no-cors` usage isn't accidentally allowed.
389
+ `Cross-Origin-Resource-Policy: same-origin` is therefore not harmful, and works to ensure that
390
+ `no-cors` usage isn't accidentally allowed.
338
391
339
392
For example, examine the headers returned when requesting endpoints like the following:
340
393
@@ -348,11 +401,13 @@ in question. A few cases are well worth considering:
348
401
should enable cross-origin embedding via `Cross-Origin-Resource-Policy`, but _not_ via CORS
349
402
access control headers:
350
403
351
- <pre class="lang-http">
352
- Cross-Origin-Resource-Policy: cross-origin
404
+ <pre highlight="http">
405
+ <strong> Cross-Origin-Resource-Policy: cross-origin</strong>
406
+ Content-Security-Policy: sandbox
407
+ Cross-Origin-Opener-Policy: same-origin
408
+ Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site
353
409
X-Content-Type-Options: nosniff
354
410
X-Frame-Options: DENY
355
- Cross-Origin-Opener-Policy: same-origin
356
411
</pre>
357
412
358
413
For example:
@@ -372,7 +427,7 @@ by making _a priori_ decisions about whether to serve the page at all (see
372
427
the page can be used once delivered. For instance, something like the following set of response
373
428
headers could be appropriate:
374
429
375
- <pre class="lang- http">
430
+ <pre highlight=" http">
376
431
Cross-Origin-Opener-Policy: same-origin
377
432
Cross-Origin-Resource-Policy: same-origin
378
433
Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site
@@ -400,7 +455,7 @@ but they can't easily lock themselves off from all such vectors via
400
455
`Cross-Origin-Opener-Policy: same-origin` and `X-Frame-Options: DENY`. In these cases, something
401
456
like the following set of response headers might be appropriate:
402
457
403
- <pre class="lang- http">
458
+ <pre highlight=" http">
404
459
Cross-Origin-Opener-Policy: same-origin-allow-popups
405
460
Cross-Origin-Resource-Policy: same-origin
406
461
Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site
@@ -427,7 +482,7 @@ or fetched cross-origin. Three scenarios are worth considering:
427
482
1. Documents that only wish to be opened in cross-origin popups could loosen their cross-origin
428
483
opener policy by serving the following headers:
429
484
430
- <pre class="lang- http">
485
+ <pre highlight=" http">
431
486
Cross-Origin-Resource-Policy: same-origin
432
487
<strong> Cross-Origin-Opener-Policy: unsafe-none</strong>
433
488
Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site
@@ -442,7 +497,7 @@ or fetched cross-origin. Three scenarios are worth considering:
442
497
2. Documents that only wish to be framed in cross-origin contexts could loosen their framing
443
498
protections by serving the following headers:
444
499
445
- <pre class="lang- http">
500
+ <pre highlight=" http">
446
501
Cross-Origin-Resource-Policy: same-origin
447
502
Cross-Origin-Opener-Policy: same-origin
448
503
Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site
@@ -457,11 +512,10 @@ or fetched cross-origin. Three scenarios are worth considering:
457
512
addition to the `X-Frame-Options` header above, the following header could also be included to
458
513
restrict the document to a short list of trusted embedders:
459
514
460
- <pre class="lang- http">
515
+ <pre highlight=" http">
461
516
Content-Security-Policy: frame-ancestors https://trusted1.example https://trusted2.example
462
517
</pre>
463
518
</div>
464
-
465
519
466
520
For example:
467
521
0 commit comments