Use of Web Link to Untrusted Target with window.opener Access
When a web page links to an external site using a standard <a> tag without the rel="noopener" attribute, the destination page gains access to the originating…
When a web page links to an external site using a standard <a> tag without the rel="noopener" attribute, the destination page gains access to the originating page's window.opener object. This allows the untrusted external site to redirect your page, steal sensitive information, or perform actions on behalf of your users — even after they've navigated away.
02How It Happens
By default, when you open a link in a new tab or window using target="_blank", the browser maintains a reference between the two pages. The newly opened page can access window.opener and call methods like window.opener.location = "malicious-site.com" to redirect your users or inject content. This is especially dangerous when linking to third-party sites you don't control — an attacker who compromises that external site, or a malicious actor who owns it, can exploit this access to attack your visitors.
The vulnerability exists because developers often forget that target="_blank" creates a bidirectional relationship, not a one-way navigation. The assumption that "the user is just going to another site" masks the fact that the other site now has a direct handle to manipulate the original page.
03Real-World Impact
An attacker controlling an external site you link to can redirect your users back to a phishing page that mimics your login form, harvest credentials, or inject malware warnings to trick users into downloading malicious files. In some cases, the attacker can read sensitive data from the opener page if it contains user-specific information in the DOM or URL. Users may not notice the redirect because they expect to be taken to a new site anyway.
04Vulnerable & Fixed Patterns
Vulnerable pattern
# Flask template rendering a link to an external site
from flask import Flask, render_template_string
app = Flask(__name__)
@app.route('/')
def index():
html = '''
<a href="https://external-partner.example.com/resource" target="_blank">
Visit Partner Site
</a>
'''
return render_template_string(html)
Why it's vulnerable: The link opens in a new tab but does not include rel="noopener", so the external site can access window.opener and manipulate the originating page.
Fixed pattern
# Flask template with rel="noopener" added
from flask import Flask, render_template_string
app = Flask(__name__)
@app.route('/')
def index():
html = '''
<a href="https://external-partner.example.com/resource" target="_blank" rel="noopener noreferrer">
Visit Partner Site
</a>
'''
return render_template_string(html)
Vulnerable pattern
<?php
// Rendering a link to an external site without rel="noopener"
$external_url = $_GET['partner_url'] ?? 'https://external-partner.example.com';
echo '<a href="' . htmlspecialchars($external_url) . '" target="_blank">Click here</a>';
?>
Why it's vulnerable: Even though the URL is escaped to prevent XSS, the missing rel="noopener" attribute allows the destination page to access and manipulate window.opener.
Fixed pattern
<?php
// Rendering a link with rel="noopener noreferrer" to prevent opener access
$external_url = $_GET['partner_url'] ?? 'https://external-partner.example.com';
echo '<a href="' . htmlspecialchars($external_url) . '" target="_blank" rel="noopener noreferrer">Click here</a>';
?>
05Prevention Checklist
Add rel="noopener noreferrer" to every <a> tag with target="_blank" that points to an external or untrusted domain.
Use rel="noopener" at minimum; noreferrer also prevents the Referer header from being sent (an additional privacy benefit).
Audit your codebase and templates for all instances of target="_blank" — use a grep or linter rule to catch new violations.
If you dynamically generate links in JavaScript, ensure the same rel attribute is applied when creating or modifying anchor elements.
Document this requirement in your security guidelines so new developers know to apply it consistently.
Consider using a Content Security Policy (CSP) with target-src directives as a secondary defense layer.
06Signs You May Already Be Affected
Check your site's HTML source code for any <a> tags with target="_blank" that lack rel="noopener" or rel="noopener noreferrer". If you find them pointing to external domains, they are vulnerable. Additionally, if users report unexpected redirects or phishing-like pages appearing after clicking external links on your site, investigate whether an external partner site has been compromised and is exploiting this weakness.