jsx-no-target-blank
Require rel='noopener noreferrer' with target='_blank'. This rule is part of eslint-plugin-react-features and provides LLM-optimized error messages.
Require rel="noopener noreferrer" with target="_blank". This rule is part of eslint-plugin-react-features and provides LLM-optimized error messages.
Quick Summary
| Aspect | Details |
|---|---|
| Severity | Warning (security) |
| Auto-Fix | 💡 Suggests fixes |
| Category | React Security |
| ESLint MCP | ✅ Optimized for ESLint MCP integration |
| Best For | All React/JSX projects |
Rule Details
Links with target="_blank" without rel="noopener noreferrer" are vulnerable to tabnabbing attacks.
Examples
❌ Incorrect
<a target="_blank" href="https://example.com">Link</a>
<a target="_blank" href={url}>External</a>✅ Correct
<a target="_blank" rel="noopener noreferrer" href="https://example.com">Link</a>
<a target="_blank" rel="noopener" href="https://example.com">Link</a>What is checked
An <a> whose target is _blank (any letter case, plain or braced) and whose href
is external (http:// / https:// in any letter case, or protocol-relative //host,
plain or braced) is reported unless rel contains noopener or noreferrer (tokens read
case-insensitively, plain or braced). noopener alone is enough.
Options
| Option | Type | Default | Description |
|---|---|---|---|
allowReferrer | boolean | false | Only changes the autofix: add noopener instead of noopener noreferrer |
enforceDynamicLinks | 'always' | 'never' | 'always' | 'always' treats a dynamic href as external and a dynamic target as _blank; 'never' leaves them unjudged |
warnOnSpreadAttributes | boolean | false | By default an element with a spread is skipped (the spread may carry rel) |
links | boolean | true | Check <a> elements |
forms | boolean | false | Also check <form target="_blank"> |
Related Rules
jsx-no-script-url- Prevent javascript URLs
Use this rule
npm install -D oxlint-plugin-react-features{ "jsPlugins": ["oxlint-plugin-react-features"], "rules": { "react-features/jsx-no-target-blank": "error" }}import { defineConfig } from 'vite-plus';export default defineConfig({ lint: { jsPlugins: ['oxlint-plugin-react-features'], rules: { 'react-features/jsx-no-target-blank': 'error', }, },});oxlint-plugin-react-features re-exports eslint-plugin-react-features/oxlint: the same rules under the same IDs, and no ESLint install. Why oxlint.
Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.