Skip to content

Instantly share code, notes, and snippets.

@yoavweiss
Last active September 17, 2024 09:21
Show Gist options
  • Save yoavweiss/c7b61e97e6f8d207be619f87ab96ead5 to your computer and use it in GitHub Desktop.
Save yoavweiss/c7b61e97e6f8d207be619f87ab96ead5 to your computer and use it in GitHub Desktop.

noopener-allow-popups Cross-Origin-Opener-Policy value

Some origins can contain different applications with different levels of security requirements. In those cases, it can be beneficial to prevent scripts running in one application from being able to open and script pages of another same-origin application. Such a document need to ensure its opener cannot script it, even if the opener document is a same-origin one.

The noopener-allow-popups Cross-Origin-Opener-Policy value severs the opener relationship between the document loaded with this policy and its opener. At the same time, the opened document can open further documents (as the "allow-popups" in the name suggests) and maintain its opener relationship with them, assuming that their COOP policy allows it.

The problem

Let's examine a hypothetical example.com origin that has two very different applications. One is https://example.com/chat that enables any user to contact any other user and send them messages. Another is https://example.com/passwords that contains all of the user's passwords, across different services.

Common security advice to further isolate these applications would be to host them on different origins. But in some cases that's not possible, and those two applications have to be on a single origin for historical/business/branding reasons.

At the same time, the administrators of the "passwords" application would very much like to ensure that it can't be directly scripted by the "chat" app, which by its nature has a larger XSS surface.

So they ask themselves the following question: if we assume that "chat" was compromised, what can prevent the attacker from reading the contents of "passwords"?

They can prevent fetch() calls on "chat" from fetching the "passwords" application HTML directly, by looking at Sec-Fetch-Mode and ensuring its value is "navigate". They can prevent "passwords" from being iframed by "chat" (or anyone) by adding an X-Frame-Options: deny or Content-Security-Policy: frame-ancestors 'none'.

But currently, they can't prevent "passwords" from being opened as a popup or a new tab, and then be scripted by the opener. If that happens, the opener has full access to the "passwords" DOM, and can use that to extract secrets from it!!

Solution: COOP: noopener-allow-popups

By providing a header that enables a document to severe its incoming opener relationship regardless of origin, we can prevent that above abuse scenario.

The opener document who would call window.open() would get back a WindowProxy that would change its closed value to true as soon as the openee document gets assigned to a browsing context group, similar to e.g. a window.open() to a document that redirects across origins.

@yoavweiss
Copy link
Author

@shhnjk - thanks! Added this to the spec!

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