Anticode Open builder

New-tab links and noopener: closing the window.opener gap

A link with target="_blank" opens in a new tab. Without rel="noopener", the page in that new tab may get a handle on the tab it came from and can send it to a different address while the visitor is looking elsewhere. Sentinel's target blank noopener check fails any page with a new-tab link that doesn't carry noopener in its rel.

Updated · By the Anticode team

The attack, step by step

The technique is usually called reverse tabnabbing. It works like this:

  1. A visitor on your site clicks a link that opens another site in a new tab.
  2. Without noopener, the new page can reach back to your tab through window.opener.
  3. While the visitor reads the new tab, its script quietly navigates your tab to a convincing copy of your site, perhaps a sign-in page.
  4. The visitor returns to what they think is your tab and types their details into the copy.

The new page doesn't need to be malicious when you link to it. A page that's later compromised, or a user-generated page on a large platform, is enough. noopener cuts the connection: the new tab opens with no reference to the page that opened it.

Why require it if browsers fixed this?

Current versions of the major browsers now treat target="_blank" links as if noopener were set, which closes most of the gap by default. Sentinel still asks for the attribute, for three reasons:

  • Not every visitor runs a current browser. Older browsers, embedded web views in apps and some less common browsers may not apply the default.
  • Intent should be explicit. Writing noopener makes the page's behaviour the same everywhere, rather than depending on the visitor's software.
  • It's free. The attribute costs nothing and changes nothing for the visitor except removing a risk.

Published Anticode sites add one more layer: they're served with a Cross-Origin-Opener-Policy: same-origin header, which separates the site's tab from cross-origin windows it opens or is opened by. The attribute and the header work together.

noopener versus noreferrer

noopener
The new tab gets no window.opener reference. The destination still sees which page sent the visitor, subject to the referrer policy.
noreferrer
Also stops the browser sending the referring address, and implies noopener in browsers that support it. Useful when the referring URL itself shouldn't be shared.
Both together
rel="noopener noreferrer" is the belt-and-braces form, covering browsers that understand one but not the other.

Anticode uses both on the links it opens in a new tab. The main example is the buy button: on a store with a payment link, each Buy button opens the checkout from the owner's provider in a new tab with rel="noopener noreferrer". Most other links on a design-engine page open in the same tab and so don't need it.

What Sentinel checks

The check finds every a element with target="_blank" and passes only if each one has noopener somewhere in its rel. The Report tab shows “New-tab links use noopener” with the number of new-tab links checked, or notes that no links open new tabs. noreferrer alone doesn't satisfy it, even though modern browsers treat it as implying noopener; the check asks for the explicit word.

Fixing a failing link

Add rel="noopener noreferrer" to the link. If it already has a rel with other values, add noopener to the list, separated by a space. Or ask whether it needs a new tab at all: opening links in the same tab is the default for good reason, and many people prefer to choose for themselves with a middle click.

Limits

  • Builder only. This check runs in Sentinel's scan in the builder; the server's publish gate doesn't repeat it. The opener-policy header is applied to published sites regardless.
  • Links, not other windows. It checks a elements. Forms with a target and windows opened from script aren't part of it; design-engine pages have no script.
  • Apps are different. App builds open outside links through their runner in a new tab, under the app's own rules; see the app sandbox.

Questions people ask

What is tabnabbing?

A page opened in a new tab uses its link back to the original tab to send that tab to a fake page. The rel noopener attribute removes that link.

Do browsers add noopener automatically now?

Current major browsers treat target blank links as noopener by default. The target blank noopener check still asks for it so behaviour doesn't depend on the visitor's browser.

Does noreferrer alone pass the check?

No. Sentinel looks for the word noopener in the rel attribute.