oxc-project/oxc · warning

Using target=`_blank` without rel=`noreferrer` (which implie

Error message

Using target=`_blank` without rel=`noreferrer` (which implies rel=`noopener`) is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations

What it means

Diagnostic from oxlint's react/jsx-no-target-blank rule, emitted when `allowReferrers` is false (the default). An `<a target="_blank">` with a non-relative href and no rel="noreferrer" lets the opened page access `window.opener` in older browsers (reverse tabnabbing) and leaks the referrer URL. The rule demands rel="noreferrer", which implies rel="noopener".

Source

Thrown at crates/oxc_linter/src/rules/react/jsx_no_target_blank.rs:25

        StringLiteral, match_expression,
    },
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use oxc_str::CompactStr;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use crate::{
    AstNode,
    context::{ContextHost, LintContext},
    rule::{DefaultRuleConfig, Rule},
    utils::is_same_expression,
};

fn target_blank_without_noreferrer(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Using target=`_blank` without rel=`noreferrer` (which implies rel=`noopener`) is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations")
        .with_help("add rel=`noreferrer` to the element")
        .with_label(span)
}

fn target_blank_without_noopener(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Using target=`_blank` without rel=`noreferrer` or rel=`noopener` (the former implies the latter and is preferred due to wider support) is a security risk: see https://mathiasbynens.github.io/rel-noopener/#recommendations")
        .with_help("add rel=`noreferrer` or rel=`noopener` to the element")
        .with_label(span)
}

fn explicit_props_in_spread_attributes(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("all spread attributes are treated as if they contain an unsafe combination of props, unless specifically overridden by props after the last spread attribute prop.")
        .with_help("add rel=`noreferrer` to the element")
        .with_label(span)
}

#[derive(Debug, Clone, JsonSchema, Deserialize, Serialize)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Add `rel="noreferrer"` to the element (`rel="noopener noreferrer"` also passes).
  2. If you must preserve the referrer, set the rule option `"allowReferrers": true` — then rel="noopener" alone satisfies the rule.
  3. Register custom link components (`settings.react.linkComponents`) so they are checked too.
  4. If the href is always same-site/relative you may set `"enforceDynamicLinks": "never"`.

Example fix

// before
<a href={userUrl} target="_blank">Profile</a>

// after
<a href={userUrl} target="_blank" rel="noreferrer">Profile</a>
Defensive patterns

Strategy: validation

Validate before calling

oxlint --react-plugin src/ # jsx-no-target-blank is on in the react plugin

# audit existing links in one pass
rg -n --no-ignore 'target=["'"']_blank' src/

Type guard

// helper that makes the safe form the easy form
type SafeLinkProps = React.AnchorHTMLAttributes<HTMLAnchorElement> & { external?: boolean };
const SafeLink = ({ external, ...rest }: SafeLinkProps) =>
  <a {...rest} rel={external ? 'noreferrer' : rest.rel} />;

Prevention

When it happens

Trigger: A link element (`<a>` or a component registered via linkComponents settings) carrying `target="_blank"` whose href/action is external or dynamic (`enforceDynamicLinks` defaults to "always", so `href={dynamicLink}` counts) and whose rel attribute does not include noreferrer. Relative hrefs (`/path`, `host-relative`) are treated as safe; the diagnostic spans the target attribute.

Common situations: Marketing/external links opening in new tabs; user-generated hrefs; forgetting rel after adding target="_blank"; custom Link components not registered in `settings.react.linkComponents` so the check is skipped (config gap, opposite problem).

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/7b20ee3df58c6c82. Report an issue: GitHub.