You’re currently viewing
Imagine the following is user-generated content on your website:Click me!!1 (same-origin)
Clicking the above link opens
malicious.html in a new tab (using
target=_blank). By itself, that’s not very exciting.
malicious.html document in this new tab has a
window.opener which points to the
window of the HTML document you’re viewing right now, i.e.
This means that once the user clicks the link,
malicious.html has full control over this document’s
Note that this also works when
malicious.html are on different origins —
window.opener.location is accessible across origins! (Things like
window.opener.document are not accessible cross-origin, though; and CORS does not apply here.) Here’s an example with a cross-origin link:
In this proof of concept,
malicious.html replaces the tab containing
index.html#hax, which displays a hidden message. This is a relatively harmless example, but instead it could’ve redirected to a phishing page, designed to look like the real
index.html, asking for login credentials. The user likely wouldn’t notice this, because the focus is on the malicious page in the new window while the redirect happens in the background. This attack could be made even more subtle by adding a delay before redirecting to the phishing page in the background (see tab nabbing).
window.opener is set, a page can trigger a navigation in the opener regardless of security origin.
To prevent pages from abusing
rel=noopener. This ensures
null in Chrome 49 and Opera 36.
For older browsers, you could use
rel=noreferrer which also disables the
Click me!!1 (now with
var otherWindow = window.open(); otherWindow.opener = null; otherWindow.location = url;
rel=noreferrer-based workaround) Click me!!1 (now with
iframe that opens the new tab, and then immediately remove the
target=_blank (or any other
target that opens a new navigation context), especially for links in user-generated content, unless you have a good reason to.
Questions? Feedback? Tweet @mathias.