Cross-Origin-Opener-Policy
(COOP) to prevent attacks from popups
origins
An origin is a URL from the browser’s point of view. Two URLs have the same origin if the following components of the URL match:
- the scheme (i.e.:
http
orhttps
) - the TLD (
.com
) - the domain (
example.com
) - the subdomain (
www.
) - the port
Notably, paths (/some/path
) and querystrings (?key=value
) and fragments (#someid
) are not part of the origin.
same-origin
policy
The same-origin policy is a security mechanism used by browsers to restrict how resources loaded from one orgin can interact with resources loaded from another. This is why cross-origin requests are blocked unless Corss Origin Resource Sharing (CORS) is enabled.
Aside from fetch()
, there are other JavaScript APIs that interact with different documents, like iframe.contentWindow
(which returns
the Window
object of an iFrame). If documents are of the same-origin, then you have direct access to the other Window
. But if they
are not, you can only access
a limited number of properties and methods
of the Window
. Despite this restriction, there are still attacks that use these APIs to leak information across origins.
vulnerabilities
Cross-site leaks ("
XS-Leaks") attack the side-channels built into web platforms to infer information about other sites.
For example, window.Length
returns the number of iframe
s in a document. Consider a scenario where this number changes based on the properties
of the user. This would make it a property that can be abused. Facebook
patched a bug that
abused this property.
Cross-Origin-Opener-Policy
Cross-Origin-Opener-Policy
is a security header that can be returned in HTTP responses which enables additional protections for when different documents
call window.open
on your site. It has three possible values:
unsafe-none
— the default (unsafe) valuesame-origin
— the most safe valuesame-origin-allow-popups
— a middle ground
Consider two different sites:
- The opener calls
window.Open()
which returns aWindow
object that references the opened site. - The opened site can use the
window.opener
property to reference theWindow
object of the opener.
Both sites can set different values for COOP. The combination of the two values controls whether or not the two documents are in the same browsing context. If they are in different browsing contexts, then:
- In the opened,
window.opener
isnull
. - in the opener,
window.open()
returns “default” values for some properties.
scenarios
Consider two web apps:
- Serves an
Index.html
that contains a button which returnswindow.open()
in open a popup in #2. - Serves a
Popup.html
which attempts to readwindow.opener
.
Scenario 1
- Both apps have the same origin.
- Result:
- The
Cross-Origin-Opener-Policy
on either app is ignored. - In the opener:
window.closed
returnsfalse
(the correct value). - In the opened:
window.opener
returns the “real”Window
object.
- The
Scenario 2 This scenario is the least secure.
- The apps have different origins.
- Both apps set
Cross-Origin-Opener-Policy: unsafe-none
(or don’t set the header at all). - Result:
window.opener
is available in the popup.- In the opener:
window.closed
returnsfalse
(the correct value). - In the opened:
window.opener
returns the realWindow
object.
Scenario 3 This scenario is the most secure.
- The apps have different origins.
- One of the apps sets
Cross-Origin-Opener-Policy: same-origin
. - Result:
- In the opener:
window.closed
returnstrue
(the incorrect value). - In the opened:
window.opener
retrunsnull
.
- In the opener:
When either app uses same-origin
, that app opts out of context sharing, and without context sharing, the result is the same regardless of which app opts out.
Scenario 4
- The apps have different origins.
- One of the apps sets
Cross-Origin-Opener-Policy: same-origin-allow-popups
. - Result:
- If the opener uses
unsafe-none
(or omits the header), the apps share browsing context. - If the opener uses anything else, the browsing contexts are isolated.
- If the opened uses
unsafe-none
, the browsing contexts are isolated.
- If the opener uses
Summary of scenarios:
Opener COOP value | Opened COOP value | Context is… |
---|---|---|
unsafe-none / missing | unsafe-none / missing | Shared |
unsafe-none / missing | same-origin-allow-popups | Isolated |
unsafe-none / missing | same-origin | Isolated |
same-origin-allow-popups | unsafe-none / missing | Shared |
same-origin-allow-popups | same-origin-allow-popups | Isolated |
same-origin-allow-popups | same-origin | Isolated |
same-origin | unsafe-none / missing | Isolated |
same-origin | same-origin-allow-popups | Isolated |
same-origin | same-origin | Isolated |
Cross-Origin-Opener-Policy-Report-Only
This header “simulates” the COOP policy and sends any violations via the browser’s reporting API.