Mike West | ee1bf436 | 2021-02-26 22:07:06 | [diff] [blame] | 1 | # Post-Spectre Web Development |
| 2 | |
| 3 | Contributors: Artur Janc, Camille Lamy, Charlie Reis, Jun Kokatsu, Mike West. |
| 4 | Patches and corrections welcome! |
| 5 | |
Mike West | c02a0098 | 2021-03-12 13:24:51 | [diff] [blame] | 6 | Last Updated: Mar. 12th, 2021 |
| 7 | |
| 8 | *** note |
| 9 | **Note**: This document has been [adopted][cfc] by the W3C's Web Application Security |
| 10 | Working Group; [https://w3c.github.io/webappsec-post-spectre-webdev/][ED] is |
| 11 | proceeding under that group's aegis, and this document will redirect there |
| 12 | once the working group is satisfied with its recommendations. |
| 13 | *** |
| 14 | |
| 15 | [cfc]: https://lists.w3.org/Archives/Public/public-webappsec/2021Feb/0007.html |
| 16 | [ED]: https://w3c.github.io/webappsec-post-spectre-webdev/ |
Mike West | ee1bf436 | 2021-02-26 22:07:06 | [diff] [blame] | 17 | |
| 18 | [TOC] |
| 19 | |
| 20 | ## Introduction |
| 21 | |
| 22 | In early 2018, [Spectre][spectre] made it clear that a foundational security |
| 23 | boundary the web aimed to maintain was substantially less robust than expected. |
| 24 | This revelation has pushed web browsers to shift their focus from the |
| 25 | platform-level origin boundary to an OS-level process boundary. Chromium's |
| 26 | [threat model][post-spectre-rethink], for instance, now asserts that "active |
| 27 | web content … will be able to read any and all data in the address space of the |
| 28 | process that hosts it". This shift in thinking imposes a shift in development |
| 29 | practice, both for browser vendors, and for web developers. Browsers need to |
| 30 | align the origin boundary with the process boundary through fundamental |
| 31 | refactoring projects (for example, Chromium's [Site Isolation][site-isolation], |
| 32 | and Firefox's [Project Fission][project-fission]). Moreover, browsers must |
| 33 | provide web developers with tools to mitigate risk in the short term, and should |
| 34 | push the platform towards safe default behaviors in the long term. The bad news |
| 35 | is that this is going to be a lot of work, much of it falling on the shoulders |
| 36 | of web developers. The good news is that a reasonable set of mitigation |
| 37 | primitives exists today, ready and waiting for use. |
| 38 | |
| 39 | This document will point to a set of mitigations which seem promising, and |
| 40 | provide concrete recommendations for web developers responsible for protecting |
| 41 | users' data. |
| 42 | |
| 43 | [spectre]: https://spectreattack.com/ |
John Palmer | 046f987 | 2021-05-24 01:24:56 | [diff] [blame] | 44 | [post-spectre-rethink]: https://chromium.googlesource.com/chromium/src/+/main/docs/security/side-channel-threat-model.md |
Mike West | ee1bf436 | 2021-02-26 22:07:06 | [diff] [blame] | 45 | [site-isolation]: https://www.chromium.org/Home/chromium-security/site-isolation |
| 46 | [project-fission]: https://wiki.mozilla.org/Project_Fission |
| 47 | |
| 48 | |
| 49 | ### Threat Model |
| 50 | |
| 51 | Spectre-like side-channel attacks inexorably lead to a model in which active web |
| 52 | content (JavaScript, WASM, probably CSS if we tried hard enough, and so on) can |
| 53 | read any and all data which has entered the address space of the process which |
| 54 | hosts it. While this has deep implications for user agent implementations' |
| 55 | internal hardening strategies (stack canaries, ASLR, etc), here we'll remain |
| 56 | focused on the core implication at the web platform level, which is both simple |
| 57 | and profound: any data which flows into a process hosting a given origin is |
| 58 | legible to that origin. We must design accordingly. |
| 59 | |
| 60 | In order to determine the scope of data that can be assumed accessible to an |
| 61 | attacker, we must make a few assumptions about the normally-not-web-exposed |
| 62 | process model which the user agent implements. The following seems like a good |
| 63 | place to start: |
| 64 | |
| 65 | 1. User agents are capable of separating the execution of a web origin's code |
| 66 | into a process distinct from the agent's core. This separation enables the |
| 67 | agent itself to access local devices, fetch resources, broker cross-process |
| 68 | communication, and so on, in a way which remains invisible to any process |
| 69 | potentially hosting untrusted code. |
| 70 | |
| 71 | 2. User agents are able to make decisions about whether or not a given resource |
| 72 | should be delivered to a process hosting a given origin based on |
| 73 | characteristics of both the request and the response (headers, etc). |
| 74 | |
| 75 | 3. User agents can consistently separate top-level, cross-origin windows into |
| 76 | distinct processes. They cannot consistently separate same-site or |
| 77 | same-origin windows into distinct processes given the potential for |
| 78 | synchronous access between the windows. |
| 79 | |
| 80 | 4. User agents cannot yet consistently separate framed origins into processes |
| 81 | distinct from their embedders' origin. |
| 82 | |
| 83 | Note: Though some user agents support [out-of-process frames][oopif], no |
| 84 | agent supports it consistently across a broad range of devices and |
| 85 | platforms. Ideally this will change over time, as the frame boundary *must* |
| 86 | be one we can eventually consider robust. |
| 87 | |
| 88 | With this in mind, our general assumption will be that an origin gains access to |
| 89 | any resource which it renders (including images, stylesheets, scripts, frames, |
| 90 | etc). Likewise, embedded frames gain access to their ancestors' content. |
| 91 | |
| 92 | This model is spelled out in more detail in both Chromium's |
| 93 | [Post-Spectre Threat Model Rethink][post-spectre-rethink], and in Artur Janc's |
| 94 | [Notes on the threat model of cross-origin isolation][coi-threat-model]. |
| 95 | |
| 96 | [oopif]: https://www.chromium.org/developers/design-documents/oop-iframes |
| 97 | [coi-threat-model]: https://arturjanc.com/coi-threat-model.pdf |
| 98 | |
| 99 | |
| 100 | ### Mitigation TL;DR |
| 101 | |
| 102 | 1. **Decide when (not!) to respond to requests** by examining incoming headers, |
| 103 | paying special attention to the `Origin` header on the one hand, and various |
| 104 | `Sec-Fetch-` prefixed headers on the other, as described in the article |
| 105 | [Protect your resources from web attacks with Fetch Metadata][fetch-metadata]. |
| 106 | |
| 107 | 2. **Restrict attackers' ability to load your data as a subresource** by |
| 108 | setting a [cross-origin resource policy][corp] (CORP) of `same-origin` |
| 109 | (opening up to `same-site` or `cross-origin` only when necessary). |
| 110 | |
| 111 | 3. **Restrict attackers' ability to frame your data as a document** by opt-ing |
| 112 | into framing protections via `X-Frame-Options: SAMEORIGIN` or CSP's more |
| 113 | granular `frame-ancestors` directive (`frame-ancestors 'self' |
| 114 | https://trusted.embedder`, for example). |
| 115 | |
| 116 | 4. **Restrict attackers' ability to obtain a handle to your window** by setting |
| 117 | a [cross-origin opener policy][coop] (COOP). In the best case, you can |
| 118 | default to a restrictive `same-origin` value, opening up to |
| 119 | `same-origin-allow-popups` or `unsafe-none` only if necessary. |
| 120 | |
| 121 | 5. **Prevent MIME-type confusion attacks** and increase the robustness of |
| 122 | passive defenses like [cross-origin read blocking][corb] (CORB) / |
| 123 | [opaque response blocking][orb] (ORB) by setting correct `Content-Type` |
| 124 | headers, and globally asserting `X-Content-Type-Options: nosniff`. |
| 125 | |
| 126 | [fetch-metadata]: https://web.dev/fetch-metadata/ |
| 127 | [corp]: https://resourcepolicy.fyi/ |
| 128 | [coop]: https://docs.google.com/document/d/1Ey3MXcLzwR1T7aarkpBXEwP7jKdd2NvQdgYvF8_8scI/edit |
John Palmer | 046f987 | 2021-05-24 01:24:56 | [diff] [blame] | 129 | [corb]: https://chromium.googlesource.com/chromium/src/+/main/services/network/cross_origin_read_blocking_explainer.md |
Mike West | ee1bf436 | 2021-02-26 22:07:06 | [diff] [blame] | 130 | [orb]: https://github.com/annevk/orb |
| 131 | |
| 132 | |
| 133 | ## Practical Examples |
| 134 | |
| 135 | ### Subresources |
| 136 | |
| 137 | Resources which are intended to be loaded into documents should protect |
| 138 | themselves from being used in unexpected ways. Before walking through strategies |
| 139 | for specific kinds of resources, a few headers seem generally applicable: |
| 140 | |
| 141 | 1. Sites should use Fetch Metadata to make good decisions about |
| 142 | [when to serve resources][fetch-metadata]. In order to ensure that decision |
| 143 | sticks, servers should explain its decision to the browser by sending a |
| 144 | `Vary` header containing `Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site`. |
| 145 | This ensures that the server has a chance to make different decisions for |
| 146 | requests which will be *used* differently. |
| 147 | |
| 148 | 2. Subresources should opt-out of MIME type sniffing by sending an |
| 149 | `X-Content-Type-Options` header with a value of `nosniff`. This increases |
| 150 | the robustness of MIME-based checks like [cross-origin read blocking][corb] |
| 151 | and [opaque response blocking][orb], and mitigates some well-known risks |
| 152 | around type confusion for scripts. |
| 153 | |
| 154 | 3. Subresources are intended for inclusion in a given context, not as |
| 155 | independently navigable documents. To mitigate the risk that navigation to a |
| 156 | subresource causes script execution or opens an origin up to attack in some |
| 157 | other way, servers can assert the following set of headers which |
| 158 | collectively make it difficult to meaningfully abuse a subresource via |
| 159 | navigation: |
| 160 | |
| 161 | * Use the `Content-Security-Policy` header to assert the `sandbox` |
| 162 | directive. This ensures that these resources remain inactive if |
| 163 | navigated to directly as a top-level document. No scripts will execute, |
| 164 | and the resource will be pushed into an "opaque" origin. |
| 165 | |
| 166 | Note: Some servers deliver `Content-Disposition: attachment; |
| 167 | filename=file.name` to obtain a similar effect. This was valuable to |
| 168 | mitigate vulnerabilies in Flash, but the `sandbox` approach seems to |
| 169 | more straightforwardly address the threats we care about today. |
| 170 | |
| 171 | * Asserting the [`Cross-Origin-Opener-Policy`][coop] header with a value |
| 172 | of `same-origin` prevents cross-origin documents from retaining a handle |
| 173 | to the resource's window if it's opened in a popup. |
| 174 | |
| 175 | * Sending the `X-Frame-Options` header with a value of `DENY` prevents the |
| 176 | resource from being framed. |
| 177 | |
| 178 | Most subresources, then, should contain the following block of headers, which |
| 179 | you'll see repeated a few times below: |
| 180 | |
| 181 | ```http |
| 182 | Content-Security-Policy: sandbox |
| 183 | Cross-Origin-Opener-Policy: same-origin |
| 184 | Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site |
| 185 | X-Content-Type-Options: nosniff |
| 186 | X-Frame-Options: DENY |
| 187 | ``` |
| 188 | |
| 189 | With these generic protections in mind, let's sift through a few scenarios to |
| 190 | determine what headers a server would be well-served to assert: |
| 191 | |
| 192 | #### Static Subresources |
| 193 | |
| 194 | By their nature, static resources contain the same data no matter who requests |
| 195 | them, and therefore cannot contain interesting information that an attacker |
| 196 | couldn't otherwise obtain. There's no risk to making these resources widely |
| 197 | available, and value in allowing embedders to robustly debug, so something like |
| 198 | the following response headers could be appropriate: |
| 199 | |
| 200 | ```http |
| 201 | Access-Control-Allow-Origin: * |
| 202 | Cross-Origin-Resource-Policy: cross-origin |
| 203 | Timing-Allow-Origin: * |
| 204 | Content-Security-Policy: sandbox |
| 205 | Cross-Origin-Opener-Policy: same-origin |
| 206 | Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site |
| 207 | X-Content-Type-Options: nosniff |
| 208 | X-Frame-Options: DENY |
| 209 | ``` |
| 210 | |
| 211 | CDNs are the canonical static resource distribution points, and many use the |
| 212 | pattern above. Take a look at the following common resources' response headers |
| 213 | for inspiration: |
| 214 | |
| 215 | * <a href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js">`https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js`</a> |
| 216 | * <a href="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js">`https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js`</a> |
| 217 | * <a href="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js">`https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js`</a> |
| 218 | * <a href="https://ssl.google-analytics.com/ga.js">`https://ssl.google-analytics.com/ga.js`</a> |
| 219 | |
| 220 | Similarly, application-specific static resource servers are a good place to look |
| 221 | for this practice. Consider: |
| 222 | |
| 223 | * <a href="https://static.xx.fbcdn.net/rsrc.php/v3/y2/r/zVvRrO8pOtu.png">`https://static.xx.fbcdn.net/rsrc.php/v3/y2/r/zVvRrO8pOtu.png`</a> |
| 224 | * <a href="https://www.gstatic.com/images/branding/googlelogo/svg/googlelogo_clr_74x24px.svg">`https://www.gstatic.com/images/branding/googlelogo/svg/googlelogo_clr_74x24px.svg`</a> |
| 225 | |
| 226 | #### Dynamic Subresources |
| 227 | |
| 228 | Subresources that contain data personalized to a given user are juicy targets |
| 229 | for attackers, and must be defended by ensuring that they're loaded only in |
| 230 | ways that are appropriate for the data in question. A few cases are well worth |
| 231 | considering: |
| 232 | |
| 233 | 1. Application-internal resources (private API endpoints, avatar images, |
| 234 | uploaded data, etc.) should not be available to any cross-origin requestor. |
| 235 | These resources should be restricted to usage as a subresource in |
| 236 | same-origin contexts by sending a [`Cross-Origin-Resource-Policy`][corp] |
| 237 | header with a value of `same-origin`: |
| 238 | |
| 239 | ```http |
| 240 | Cross-Origin-Resource-Policy: same-origin |
| 241 | Content-Security-Policy: sandbox |
| 242 | Cross-Origin-Opener-Policy: same-origin |
| 243 | Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site |
| 244 | X-Content-Type-Options: nosniff |
| 245 | X-Frame-Options: DENY |
| 246 | ``` |
| 247 | |
| 248 | This header will prevent cross-origin attackers from loading the resource as |
| 249 | a response to a `no-cors` request. |
| 250 | |
| 251 | For example, examine the headers returned when requesting endpoints like the |
| 252 | following: |
| 253 | |
| 254 | * <a href="https://myaccount.google.com/_/AccountSettingsUi/browserinfo">`https://myaccount.google.com/_/AccountSettingsUi/browserinfo`</a> |
| 255 | * <a href="https://twitter.com/i/api/1.1/branch/init.json">`https://twitter.com/i/api/1.1/branch/init.json`</a> |
| 256 | * <a href="https://www.facebook.com/ajax/webstorage/process_keys/?state=0">`https://www.facebook.com/ajax/webstorage/process_keys/?state=0`</a> |
| 257 | |
| 258 | 2. Personalized resources intended for cross-origin use (public API endpoints, |
| 259 | etc) should carefully consider incoming requests' properties before |
| 260 | responding. These endpoints can only safely be enabled by requiring CORS, |
| 261 | and choosing the set of origins for which a given response can be exposed by |
| 262 | setting the appropriate access-control headers, for example: |
| 263 | |
| 264 | ```http |
| 265 | Access-Control-Allow-Credentials: true |
| 266 | Access-Control-Allow-Origin: https://trusted.example |
| 267 | Access-Control-Allow-Methods: POST |
| 268 | Access-Control-Allow-Headers: ... |
| 269 | Access-Control-Allow-...: ... |
| 270 | Cross-Origin-Resource-Policy: same-origin |
| 271 | Content-Security-Policy: sandbox |
| 272 | Cross-Origin-Opener-Policy: same-origin |
| 273 | Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site |
| 274 | X-Content-Type-Options: nosniff |
| 275 | X-Frame-Options: DENY |
| 276 | ``` |
| 277 | |
| 278 | Note: The `Cross-Origin-Resource-Policy` header is only processed for |
| 279 | requests that are _not_ using CORS for access control ("`no-cors` |
| 280 | requests"). Sending `Cross-Origin-Resource-Policy: same-origin` is |
| 281 | therefore not harmful, and works to ensure that `no-cors` usage isn't |
| 282 | accidentally allowed. |
| 283 | |
| 284 | For example, examine the headers returned when requesting endpoints like |
| 285 | the following: |
| 286 | |
| 287 | * <a href="https://api.twitter.com/1.1/jot/client_event.json">`https://api.twitter.com/1.1/jot/client_event.json`</a> |
| 288 | * <a href="https://play.google.com/log?format=json&hasfast=true">`https://play.google.com/log?format=json&hasfast=true`</a> |
| 289 | * <a href="https://securepubads.g.doubleclick.net/pcs/view">`https://securepubads.g.doubleclick.net/pcs/view`</a> |
| 290 | * <a href="https://c.amazon-adsystem.com/e/dtb/bid">`https://c.amazon-adsystem.com/e/dtb/bid`</a> |
| 291 | |
| 292 | 3. Personalized resources that are intended for cross-origin `no-cors` |
| 293 | embedding, but which don't intend to be directly legible in that context |
| 294 | (avatar images, authenticated media, etc). These should enable cross-origin |
| 295 | embedding via `Cross-Origin-Resource-Policy`, but _not_ via CORS access |
| 296 | control headers: |
| 297 | |
| 298 | ```http |
| 299 | Cross-Origin-Resource-Policy: cross-origin |
| 300 | Content-Security-Policy: sandbox |
| 301 | Cross-Origin-Opener-Policy: same-origin |
| 302 | Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site |
| 303 | X-Content-Type-Options: nosniff |
| 304 | X-Frame-Options: DENY |
| 305 | ``` |
| 306 | |
| 307 | Note, that this allows the resource to be used by any cross-origin document. |
| 308 | That's reasonable for some use cases, but requiring CORS, and opting-in a |
| 309 | small set of origins via appropriate access-control headers is a possible |
| 310 | alternative for some resources. This approach will give those contexts |
| 311 | trivial access to the resource's bits, so the granularity is a tradeoff. |
| 312 | Still, considering this case to be the same as the "personalized resources |
| 313 | intended for cross-origin use" isn't unreasonable. |
| 314 | |
| 315 | If we implemented more granular bindings for CORP headers (along the lines |
| 316 | of `Cross-Origin-Resource-Policy: https://trusted.example`), we could avoid |
| 317 | this tradeoff entirely. That's proposed in |
| 318 | [whatwg/fetch#760](https://github.com/whatwg/fetch/issues/670). |
| 319 | |
| 320 | |
| 321 | For example: |
| 322 | |
| 323 | * <a href="https://lh3.google.com/u/0/d/1JBUaX1xSOZRxBk5bRNZWgnzyJoCQC52TIRokACBSmGc=w512">`https://lh3.google.com/u/0/d/1JBUaX1xSOZRxBk5bRNZWgnzyJoCQC52TIRokACBSmGc=w512`</a> |
| 324 | |
| 325 | |
| 326 | ### Documents {#documents} |
| 327 | |
| 328 | #### Fully-Isolated Documents |
| 329 | |
| 330 | Documents that require users to be signed-in almost certainly contain |
| 331 | information that shouldn't be revealed to attackers. These pages should take |
| 332 | care to isolate themselves from other origins, both by making _a priori_ |
| 333 | decisions about [whether to serve the page at all][fetch-metadata], and by |
| 334 | giving clients careful instructions about how the page can be used once |
| 335 | delivered. For instance, something like the following set of response headers |
| 336 | could be appropriate: |
| 337 | |
| 338 | ```http |
| 339 | Cross-Origin-Opener-Policy: same-origin |
| 340 | Cross-Origin-Resource-Policy: same-origin |
| 341 | Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site |
| 342 | X-Content-Type-Options: nosniff |
| 343 | X-Frame-Options: SAMEORIGIN |
| 344 | ``` |
| 345 | |
| 346 | Note: Documents which need to make use of APIs that require full cross-origin |
| 347 | isolation (such as `SharedArrayBuffer`), will also need to serve a |
| 348 | [`Cross-Origin-Embedder-Policy`][coep] header, as outlined in |
| 349 | [Making your website "cross-origin isolated" using COOP and COEP][coop-coep]. |
| 350 | |
| 351 | Account settings pages, admin panels, and application-specific documents are all |
| 352 | good examples of resources which would benefit from as much isolation as |
| 353 | possible. For real-life examples, consider: |
| 354 | |
| 355 | * <a href="https://myaccount.google.com/">`https://myaccount.google.com/`</a> |
| 356 | |
| 357 | [coep]: https://wicg.github.io/cross-origin-embedder-policy/ |
| 358 | [coop-coep]: https://web.dev/coop-coep/ |
| 359 | |
| 360 | |
| 361 | #### Documents Expecting to Open Cross-Origin Windows |
| 362 | |
| 363 | Not every document that requires sign-in can be fully-isolated from the rest of |
| 364 | the internet. It's often the case that partial isolation is a better fit. |
| 365 | Consider sites that depend upon cross-origin windows for federated workflows |
| 366 | involving payments or sign-in, for example. These pages would generally benefit |
| 367 | from restricting attackers' ability to embed them, or obtain their window |
| 368 | handle, but they can't easily lock themselves off from all such vectors via |
| 369 | `Cross-Origin-Opener-Policy: same-origin` and `X-Frame-Options: DENY`. In these |
| 370 | cases, something like the following set of response headers might be |
| 371 | appropriate: |
| 372 | |
| 373 | ```http |
| 374 | Cross-Origin-Opener-Policy: same-origin-allow-popups |
| 375 | Cross-Origin-Resource-Policy: same-origin |
| 376 | Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site |
| 377 | X-Content-Type-Options: nosniff |
| 378 | X-Frame-Options: SAMEORIGIN |
| 379 | ``` |
| 380 | |
| 381 | The only difference between this case and the "Fully-Isolated" case above is the |
| 382 | `Cross-Origin-Opener-Policy` value. `same-origin` will break the opener |
| 383 | relationship between the document and any cross-origin window, regardless of who |
| 384 | opened whom. `same-origin-allow-popups` will break cross-origin opener |
| 385 | relationships initiated by a cross-origin document's use of `window.open()`, but |
| 386 | will allow the asserting document to open cross-origin windows that retain an |
| 387 | opener relationship. |
| 388 | |
| 389 | |
| 390 | #### Documents Expecting Cross-Origin Openers |
| 391 | |
| 392 | Federated sign-in forms and payment providers are clear examples of documents |
| 393 | which intend to be opened by cross-origin windows, and require that relationship |
| 394 | to be maintained in order to facilitate communication via channels like |
| 395 | `postMessage()` or navigation. These documents cannot isolate themselves |
| 396 | completely, but can prevent themselves from being embedded or fetched |
| 397 | cross-origin. Three scenarios are worth considering: |
| 398 | |
| 399 | 1. Documents that only wish to be opened in cross-origin popups could loosen |
| 400 | their cross-origin opener policy by serving the following headers: |
| 401 | |
| 402 | ```http |
| 403 | Cross-Origin-Resource-Policy: same-origin |
| 404 | Cross-Origin-Opener-Policy: unsafe-none |
| 405 | Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site |
| 406 | X-Content-Type-Options: nosniff |
| 407 | X-Frame-Options: SAMEORIGIN |
| 408 | ``` |
| 409 | |
| 410 | For example: |
| 411 | |
| 412 | * > TODO: Find some links. |
| 413 | |
| 414 | 2. Documents that only wish to be framed in cross-origin contexts could loosen |
| 415 | their framing protections by serving the following headers: |
| 416 | |
| 417 | ```http |
| 418 | Cross-Origin-Resource-Policy: same-origin |
| 419 | Cross-Origin-Opener-Policy: same-origin |
| 420 | Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site |
| 421 | X-Content-Type-Options: nosniff |
| 422 | X-Frame-Options: ALLOWALL |
| 423 | ``` |
| 424 | |
| 425 | |
| 426 | Note that this allows embedding by any cross-origin documents. That's |
| 427 | reasonable for some widgety use cases, but when possible, a more secure |
| 428 | alternative would specify a list of origins which are allowed to embed the |
| 429 | document via the `frame-ancestors` CSP directive. That is, in addition to |
| 430 | the `X-Frame-Options` header above, the following header could also be |
| 431 | included to restrict the document to a short list of trusted embedders: |
| 432 | |
| 433 | ```http |
| 434 | Content-Security-Policy: frame-ancestors https://trusted1.example https://trusted2.example |
| 435 | ``` |
| 436 | |
| 437 | For example: |
| 438 | |
| 439 | * > TODO: Find some links. |
| 440 | |
| 441 | 3. Documents that support both popup and framing scenarios need to loosen both |
| 442 | their cross-origin opener policies and framing protections by combining the |
| 443 | recommendations above, serving the following headers: |
| 444 | |
| 445 | ```http |
| 446 | Cross-Origin-Resource-Policy: same-origin |
| 447 | Cross-Origin-Opener-Policy: unsafe-none |
| 448 | Vary: Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site |
| 449 | X-Content-Type-Options: nosniff |
| 450 | X-Frame-Options: ALLOWALL |
| 451 | ``` |
| 452 | |
| 453 | For example: |
| 454 | |
| 455 | * > TODO: Find some links. |
| 456 | |
| 457 | ## Implementation Considerations |
| 458 | |
| 459 | ### Explicitly Setting Headers with Default Values |
| 460 | |
| 461 | Several recommendations above suggest that developers would be well-served to |
| 462 | set headers like `X-Frame-Options: ALLOWALL` or `Cross-Origin-Opener-Policy: |
| 463 | unsafe-none` on responses. These map to the web's status quo behavior, and seem |
| 464 | therefore superfluous. Why should developers set them? |
| 465 | |
| 466 | The core reason is that these defaults are poor fits for today's threats, and we |
| 467 | ought to be working to change them. Proposals like [Embedding Requires Opt-In][embedding] |
| 468 | and [COOP By Default][coop-by-default] suggest that we should shift the web's |
| 469 | defaults away from requiring developers to opt-into more secure behaviors by |
| 470 | making them opt-out rather than opt-in. This would place the configuration cost |
| 471 | on those developers whose projects require risky settings. |
| 472 | |
| 473 | This document recommends setting those less-secure header values explicitly, as |
| 474 | that makes it more likely that we'll be able to shift the web's defaults in the |
| 475 | future. |
| 476 | |
| 477 | [embedding]: https://github.com/mikewest/embedding-requires-opt-in |
| 478 | [coop-by-default]: https://github.com/mikewest/coop-by-default |
| 479 | |
| 480 | ## Acknowledgements |
| 481 | |
| 482 | This document relies upon a number of excellent resources that spell out much of |
| 483 | the foundation of our understanding of Spectre's implications for the web, and |
| 484 | justify the mitigation strategies we currently espouse. The following is an |
| 485 | incomplete list of those works, in no particular order: |
| 486 | |
| 487 | * Chris Palmer's |
| 488 | [Isolating Application-Defined Principles](https://noncombatant.org/application-principals/) |
| 489 | |
| 490 | * Charlie Reis' |
| 491 | [Long-Term Web Browser Mitigations for Spectre](https://docs.google.com/document/d/1dnUjxfGWnvhQEIyCZb0F2LmCZ9gio6ogu2rhMGqi6gY/edit) |
| 492 | |
| 493 | * Anne van Kesteren's |
| 494 | [A Spectre-Shaped Web](https://docs.google.com/presentation/d/1sadl7jTrBIECCanuqSrNndnDr82NGW1yyuXFT1Dc7SQ/edit#slide=id.p), |
| 495 | [Safely Reviving Shared Memory](https://hacks.mozilla.org/2020/07/safely-reviving-shared-memory/), |
| 496 | and [Opaque Resource Blocking](https://github.com/annevk/orb). |
| 497 | |
| 498 | * Artur Janc and Mike West's [How do we stop spilling the beans across origins?](https://www.arturjanc.com/cross-origin-infoleaks.pdf) |
| 499 | |
| 500 | * Mike West's [Cross-Origin Embedder Policy explainer](https://wicg.github.io/cross-origin-embedder-policy/) |
| 501 | |
| 502 | * Charlie Reis and Camille Lamy's [Cross-Origin Opener Policy explainer](https://docs.google.com/document/d/1Ey3MXcLzwR1T7aarkpBXEwP7jKdd2NvQdgYvF8_8scI/edit) |
| 503 | |
| 504 | * Artur Janc, Charlie Reis, and Anne van Kesteren's [COOP and COEP Explained](https://docs.google.com/document/d/1Ey3MXcLzwR1T7aarkpBXEwP7jKdd2NvQdgYvF8_8scI/edit) |
| 505 | |
| 506 | * Artur Janc's [Notes on the threat model of cross-origin isolation](https://arturjanc.com/coi-threat-model.pdf) |