Skip to content

Instantly share code, notes, and snippets.

@annevk

annevk/coop.md Secret

Last active June 25, 2021 00:39
  • Star 11 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save annevk/6f2dd8c79c77123f39797f6bdac43f3e to your computer and use it in GitHub Desktop.

Cross-Origin-Opener-Policy response header (also known as COOP)

Introduction

This is a semi-formal definition of the Cross-Origin-Opener-Policy response header, to be merged into the HTML Standard pending various refactoring efforts. (See also the open issues.)

COOP can be used to prevent a site from opening a site with COOP in an auxiliary browsing context. The site attempting to do so will hold a reference to a closed browsing context and the site using COOP will be in a fresh top-level browsing context with its own browsing context group. A site using COOP can open auxiliary browsing contexts itself, if they are same-origin and also use COOP, or if it uses the same-origin-allow-popups COOP policy.

Goal

Integrate this into the HTML Standard.

Model

This should only work over a secure context.

To ensure robust isolation the processing model also needs to account for the Cross-Origin-Embedder-Policy response header (also known as COEP) to some extent. This document only defines how it augments COOP.

Document's have an associated cross-origin opener-policy, which is "same-origin + COEP", "same-origin", "same-origin-allow-popups", or "unsafe-none". It's initially "unsafe-none". (XXX: document creation needs to use "obtaining a cross-origin opener-policy".)

Note: "same-origin + COEP" is a special value that cannot be directly set, but is the result of setting COOP and COEP for a top-level document at the same time.

about:blank documents inherit cross-origin opener-policy from their creator's top-level browsing context's active document at the time of creation, if there is a creator and if the creator's origin is same origin with the creator's top-level origin.


To obtain a cross-origin opener-policy from a response response:

  1. Let value be the result of getting Cross-Origin-Opener-Policy from response's header list.
  2. If value is null, then return "unsafe-none".
  3. Let decodedValue be value, isomorphic decoded. (XXX: we should change Fetch so we can merge this into step 1.)
  4. If decodedValue is not "same-origin" or "same-origin-allow-popups", then return "unsafe-none".
  5. If decodedValue is "same-origin", then:
    1. Let coep be the result of obtaining a cross-origin embedder-policy from response. (XXX: the integration probably needs some slight adjustments as even if COOP ends up being "unsafe-none", we'd still want to respect COEP for non-COOP purposes. If we process COEP before COOP we could pass COEP into this algorithm instead.)
    2. If coep is "require-corp", then return "same-origin + COEP".
  6. Return decodedValue.

Note: the Cross-Origin-Opener-Policy header part is roughly equivalent to this non-normative ABNF:

Cross-Origin-Opener-Policy = %s"same-origin" / %s"same-origin-allow-popups" / %s"unsafe-none"; case-sensitive

To match cross-origin opener-policies, given A, originA, B, and originB:

  1. If A is "unsafe-none" and B is "unsafe-none", then return true.
  2. If A or B is "unsafe-none", then return false.
  3. If A is B and originA is same origin with originB, then return true.
  4. Return false.

Changes to navigation

Then, when navigating from a document doc in a top-level browsing context bc to a response response:

  1. Let currentCOOP be doc's cross-origin opener-policy.

  2. Let currentOrigin be doc's origin.

  3. Let potentialCOOP be the result of obtaining a cross-origin opener-policy from response.

  4. Let potentialOrigin be response's URL's origin. TODO: this should take CSP into account as that can make it an opaque origin (and future policies that can do similar things).

  5. If bc's popup sandboxing flag set is not empty and potentialCOOP is not "unsafe-none", then navigate bc to a network error and abort these steps.

    Note: This results in a network error as one cannot simultaneously provide a clean slate to a response using cross-origin opener policy and sandbox the result of navigating to that response.

  6. If the result of matching currentCOOP, currentOrigin, potentialCOOP, and potentialOrigin is false and one of the following is false

    • doc is the initial about:blank document
    • currentCOOP is "same-origin-allow-popups"
    • potentialCOOP is "unsafe-none"

    then:

    1. Let bcg be the result of creating a new browsing context group.
    2. If potentialCOOP is "same-origin + COEP", then set bcg's cross-origin isolated to true.
    3. Move loading of response to a new top-level browsing context newTLBC in bcg.
    4. If bc's popup sandboxing flag set is not empty, then:
      1. Assert: potentialCOOP is "unsafe-none".
      2. Set newTLBC's popup sandboxing flag set to bc's popup sandboxing flag set.
    5. Discard bc. [Note: this does not close bc's browsing context group, except if it was the sole top-level browsing context in which case it could be collected.]
  7. Otherwise, [do the normal thing].

Note: the intent is that this runs for each response, including redirects. User agents are expected to optimize away the many browsing context groups that would be created through a redirect chain, by keeping track as to whether it is needed at all.

Changes to choosing a browsing context

Then, a change is needed to "If the user agent has been configured such that in this instance it will create a new browsing context", which is part of the "The rules for choosing a browsing context" algorithm. In particular before the current algorithm runs:

  1. If current's top-level browsing context's active document's cross-origin opener-policy is "same-origin" or "same-origin + COEP", then:
    1. Let currentDoc be current's active document.
    2. If currentDoc's origin is not same origin with currentDoc's top-level origin, then set noopener to true and name to "_blank".

Additional implications of "same-origin + COEP"

  • It impacts postMessage() and causes window.crossOriginIsolated to return true as detailed in HTML PR #4734.
  • As described in that same PR and proposed in issue #5122 it also impacts keying of agent clusters in the newly created browsing context (using origin rather than site as the key) as well as no-opping the document.domain setter. This still needs some compatibility analysis.
@guest271314
Copy link

@annevk Updated Nightly to 80.0a1 (2020-07-20) and the preferences do now work at plnkr. However, Headers from fetch() still do not include Content-Length, so it is impossible to do this

          const { headers, body, ok } = await fetch(url, { cache: 'no-store' });
          const length = +headers.get('content-length');
           // ...
          const memory = new WebAssembly.Memory({
            initial: Math.floor(length / 65536) + 1,
            maximum: Math.floor(length / 65536) + 1,
            shared: true,
          });

at Mozilla browers https://bugzilla.mozilla.org/show_bug.cgi?id=1654212.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment