Why are noopener and noreferrer important on `<a target="_blank">`
`target='_blank'` opens a new tab/window where the new page gets a `window.opener` reference back to your page — letting it run `window.opener.location = 'phishing-url'` (reverse tabnabbing). `rel='noopener'` blocks that. `rel='noreferrer'` additionally strips the `Referer` header. Modern browsers add `noopener` implicitly, but the rel attribute remains best practice.
When you open a link in a new tab/window with target="_blank", by default the destination page gets a reference back to your page via window.opener. That's both a security and a performance problem.
The attack — reverse tabnabbing
<a href="https://attacker.example" target="_blank">Check this out</a>On the destination page, an attacker can do:
if (window.opener) {
window.opener.location = "https://phishing.example/login";
}The original tab (still in the background) silently navigates to a phishing page that looks like your site's login. The user switches back, sees their familiar-looking site asking for a password, and types it in.
This is called reverse tabnabbing or "tabnabbing via window.opener."
The fix — rel="noopener"
rel="noopener" tells the browser not to set window.opener on the destination. Now window.opener === null in the new tab; the attacker can't navigate your tab.
<a href="https://example.com" target="_blank" rel="noopener">Link</a>Bonus — rel="noreferrer"
rel="noreferrer" does everything noopener does and strips the Referer header. Useful when you don't want the destination to know which page on your site sent the user.
<a href="https://example.com" target="_blank" rel="noopener noreferrer">Link</a>In practice, noreferrer implies noopener in all modern browsers — but explicitly listing both is clearer and works on older clients.
What about modern browsers?
Since Chrome 88 / Firefox 79 / Safari 12.1 (~2020), browsers implicitly apply noopener when target="_blank" is used. So new-browser users are safe by default.
But:
- Older browsers still need the explicit attribute.
- Embedded webviews and older systems lag.
- Many security scanners (lint, audit tools) still flag missing
reland you'll waste time defending it in PRs. - Explicit rel signals intent in the code review.
Always include rel="noopener noreferrer" on external target="_blank" links. It costs nothing.
Performance bonus
Without noopener, the new tab runs in the same process as the opener (in some browsers) so it can synchronously script window.opener. With noopener, the browser can isolate the new tab in a separate process — better performance and crash isolation.
When you DO want window.opener
Rare. Sometimes a same-origin popup needs to communicate back. Use window.postMessage instead of relying on window.opener access; it's safer.
What about JS-opened windows?
window.open(url) has the same vulnerability. Mitigate:
const win = window.open(url);
if (win) win.opener = null;
// or use the newer noopener feature:
window.open(url, "_blank", "noopener,noreferrer");Linting it
Most React lint configs include the rule react/jsx-no-target-blank to catch missing rel on target="_blank". Enable it.
Interview framing
"target='_blank' gives the destination tab a reference to your tab via window.opener. An attacker on the destination can use that to silently navigate your tab to a phishing page — reverse tabnabbing. rel='noopener' blocks that by setting window.opener to null in the new tab. rel='noreferrer' additionally strips the Referer header. Since 2020, browsers apply noopener implicitly with _blank, but I still include rel='noopener noreferrer' explicitly for older browsers, security scanners, and intent in code review. There's also a performance bonus — the new tab can run in its own process."
Follow-up questions
- •How exactly does reverse tabnabbing work?
- •Why does modern Chrome already protect against this?
- •What does noreferrer do that noopener doesn't?
- •How would you safely communicate between an opener and the new tab?
Common mistakes
- •Omitting rel on `target='_blank'`.
- •Assuming modern browsers handle it — but linters / security audits still flag.
- •Using `window.opener` for legitimate cross-tab communication instead of postMessage.
Performance considerations
- •noopener lets the browser isolate the new tab in a separate process — better crash isolation and parallelism.
Edge cases
- •Embedded WebViews / older OSes without implicit noopener.
- •Same-origin opener that legitimately needs communication.
- •Server-rendered links from untrusted user content (markdown comments) — always sanitize.
Real-world examples
- •Hacker News and forum software apply noopener+noreferrer on user-submitted external links.
- •GitHub adds rel on any external link in issue/PR markdown.