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:

  1. 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").
  2. New Tab Focus: The browser opens the attacker’s page (Site B) in a new tab, shifting user focus away from Site A.
  3. 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.
  4. 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>

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.