Skip to content

VNX-1022: New window opened to an untrusted target with window.opener access (tabnabbing)

Reports target="_blank" links to dynamic URLs without rel="noopener noreferrer", links with rel="opener", and window.open() to a variable URL without noopener (reverse tabnabbing).

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-1022
Severity Medium
SARIF level warning
Kind sast
Languages HTML, JavaScript / TypeScript
CWE CWE-1022
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C
Tags target-blank tabnabbing window-opener cwe-1022
Source internal/sast/rules/vnx-1022.rego

Overview

VNX-1022 maps to CWE-1022: Use of Web Link to Untrusted Target with window.opener Access. It reports:

  • an <a>, <area>, <form>, <Link> or <NavLink> with target="_blank" whose URL comes from an expression (JSX {expr}, Vue :href, Angular [href], Thymeleaf th:href="${...}", or a value starting with {{ }}, <%= %>, <?= ?>, ${ } or Razor @) and no rel containing noopener or noreferrer;
  • any such tag with rel="opener";
  • window.open(url, ...) with a non-constant URL, no noopener/noreferrer feature and no .opener = null on the result.

Not reported: links and window.open calls with a fixed URL or a fixed host and an interpolated path (current browsers apply noopener to target="_blank" anchors by default, and a fixed link names a site the author chose), relative links and template route helpers ({{ url_for(...) }}, {{ path(...) }}, {% url %}, *_path, Hugo .Permalink/.RelPermalink, Jekyll site.baseurl), window.open to _self/_parent/_top, comments and test files.

Why This Matters

A page opened with window.opener access can set window.opener.location and quietly replace the original tab with a phishing copy of it while the user is looking at the new tab. When the URL comes from user content (a profile website, a shared link), the attacker controls the opened page.

What Gets Flagged

<a href={user.website} target="_blank">Website</a>
<a href="{{ post.source_url }}" target="_blank">{{ post.source }}</a>
<a href="https://partner.example/" target="_blank" rel="opener">Partner</a>
window.open(target, '_blank');

Remediation

  1. Add rel="noopener noreferrer" to every target="_blank" link whose URL is not fixed.
  2. Pass 'noopener,noreferrer' as the third argument of window.open, or set newWindow.opener = null.
  3. Never use rel="opener" for a link to another origin.

References

Suppressing this rule

Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):

# nosec vnx-1022
// nosec vnx-1022

Or record an ignore rule: vulnetix ignore add --rule vnx-1022 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-1022.rego, cli/internal/sast/docs/vnx-1022.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.