CSPv3 specifies a new disown-opener policy:
The disown-opener directive ensures that a resource will disown its opener when navigated to.
The linked WHATWG spec isn't very helpful either:
The opener IDL attribute on the Window object, on getting, must return the WindowProxy object of the browsing context from which the current browsing context was created (its opener browsing context), if there is one, if it is still available, and if the current browsing context has not disowned its opener; otherwise, it must return null. On setting, if the new value is null then the current browsing context must disown its opener; if the new value is anything else then the user agent must call the [[DefineOwnProperty]] internal method of the Window object, passing the property name "opener" as the property key, and the Property Descriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true } as the property descriptor, where value is the new value.
It causes window.opener
to be set to null
on any new windows or tabs that get navigated to from any document served with a CSP header containing the disown-opener
directive.
The use case is similar to the one for rel=noopener
.
The class of attack both are meant to prevent is caused by the fact that when you have links in your document A to a document B (potentially at another origin), any script at document B can through the value of window.opener
access and control the window object at document A.
So document B’s script can change the window.opener.location
for the window document A is in to the URL of document C, so that window navigates away from document A to that URL.
If document C is designed to look exactly like document A—e.g., including a spoofed login form—it could be used to trick the user and phish user credentials.
Mathias Bynens covers this in detail in About rel=noopener: What problems does it solve?.
Setting window.opener
to null
on the document being navigated to prevents the problem.
Without disown-opener
for the use case it addresses, document A first would need to open a new tab/window to a document/location it controls, then use script to set window.opener
to null
, then have the script at the document in that tab/window navigate it to document B.
Update 1: I’ve raised a PR against the HTML spec to add informative notes to the spec for this.
Update 2: The patch from the PR above was merged into the HTML spec, so it now says this:
If a browsing context is disowned, its
window.opener
attribute is null. That prevents scripts in the browsing context from changing any properties of its opener browsing context'sWindow
object (i.e., theWindow
object from which the browsing context was created).Otherwise, if a browsing context is not disowned, then scripts in that browsing context can use
window.opener
to change properties of its opener browsing context'sWindow
object. For example, a script running in the browsing context can change the value ofwindow.opener.location
, causing the opener browsing context to navigate to a completely different document.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With