Window Opener Reverse Tabnabbing in JavaScript
Reverse tabnabbing is a web security vulnerability where an attacker
manipulates the origin tab of a newly opened page to execute phishing
attacks or distribute malware. This vulnerability arises primarily
through the window.opener JavaScript property, which grants
a newly opened document a partial reference to the parent document that
launched it. By exploiting this relationship, malicious pages can
quietly alter the original page’s destination URL while the user is
focused on the new tab, tricking them into interacting with a fraudulent
website.
Understanding the Role
of window.opener
When a website creates a new browsing context using an anchor tag
with target="_blank" or through window.open(),
the target window automatically retains a reference to the source window
via window.opener.
Even though the Same-Origin Policy (SOP) blocks cross-origin
documents from reading sensitive properties, cookies, or DOM elements of
another origin, SOP permits cross-origin modifications to specific
navigation properties. Most notably, a newly opened page is allowed to
modify the window.opener.location property.
// Malicious script running in the newly opened tab
if (window.opener) {
window.opener.location = "https://phishing-site.example.com/fake-login";
}How the Attack is Executed
The attack relies heavily on user psychology and background manipulation:
- Link Interaction: A user on a trusted website (Site
A) clicks a user-submitted link or an external link configured to open
in a new tab (
target="_blank"). - New Tab Focus: The browser opens the attacker’s page (Site B) in a new tab, shifting user focus away from Site A.
- Silent Redirection: While the user is browsing Site
B, a script on Site B modifies
window.opener.location, redirecting the background tab (Site A) to a visually identical phishing page. - Credential Harvesting: When the user finishes with Site B and closes the tab, they return to the original tab. Seeing a login prompt on what appears to be Site A, the user assumes their session expired and enters their credentials, sending them directly to the attacker.
Programmatic
Vulnerabilities with window.open()
Reverse tabnabbing is not limited to HTML links; it also affects
dynamic JavaScript window creation. Calling
window.open(url, '_blank') without explicitly disabling the
opener link exposes the calling window to the same risk.
// Vulnerable implementation
const externalTab = window.open('https://untrusted-website.example.com', '_blank');
// Secure implementation
const secureTab = window.open('https://untrusted-website.example.com', '_blank', 'noopener,noreferrer');
if (secureTab) {
secureTab.opener = null;
}Mitigation Strategies
To defend against reverse tabnabbing, developers must ensure that child contexts do not retain references to their parent documents.
1. Using
rel="noopener" and rel="noreferrer"
Whenever defining an external link with target="_blank",
include rel="noopener noreferrer" in the anchor tag:
<a href="https://example.com" target="_blank" rel="noopener noreferrer">
Visit External Site
</a>noopener: Instructs the browser to open the link without giving the new context access towindow.opener, setting it tonull.noreferrer: Prevents the browser from sending theRefererheader to the target site while also implyingnoopenerbehavior in older browsers.
2. Utilizing Modern Browser Defaults
Modern web browsers (including recent versions of Chrome, Firefox,
Safari, and Edge) automatically apply rel="noopener"
behavior to any <a> element containing
target="_blank". However, relying entirely on browser
defaults leaves legacy browsers and programmatic
window.open() calls unprotected.
3. Implementing Cross-Origin-Opener-Policy (COOP)
At the server level, delivering the
Cross-Origin-Opener-Policy (COOP) HTTP response header
provides document-wide protection:
Cross-Origin-Opener-Policy: same-origin
This header isolates the top-level document from cross-origin
documents by ensuring that other origins opened in new tabs run in
separate browsing context groups, fundamentally neutralizing
window.opener exploitation.