oxc-project/oxc · error · OxcDiagnostic

React 19 disallows `javascript:` URLs as a security precauti

Error message

React 19 disallows `javascript:` URLs as a security precaution.

What it means

Diagnostic from react/jsx-no-script-url (category: suspicious). It flags javascript: URLs in link attributes — <a href="javascript:void(0)"> — because such URLs are an XSS vector when unsanitized data reaches them. The matcher (JS_SCRIPT_REGEX) tolerates mixed case and embedded \r/\n/\t between the letters, so obfuscated variants like 'jav\tascript:...' are still caught. React 16.9 warned about these URLs and React 19 disallows them entirely, hence the message; the help suggests using event handlers instead.

Source

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

    },
};
use serde::Deserialize;
use serde_json::Value;

use oxc_ast::{AstKind, ast::JSXAttributeItem};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use oxc_str::CompactStr;

use crate::{
    AstNode,
    context::{ContextHost, LintContext},
    rule::{MixedTupleRuleConfig, Rule},
};

fn jsx_no_script_url_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("React 19 disallows `javascript:` URLs as a security precaution.")
        .with_help("Use event handlers instead if you can.")
        .with_label(span)
}

static JS_SCRIPT_REGEX: Lazy<Regex> = lazy_regex!(
    r"(j|J)[\r\n\t]*(a|A)[\r\n\t]*(v|V)[\r\n\t]*(a|A)[\r\n\t]*(s|S)[\r\n\t]*(c|C)[\r\n\t]*(r|R)[\r\n\t]*(i|I)[\r\n\t]*(p|P)[\r\n\t]*(t|T)[\r\n\t]*:"
);

#[derive(Debug, Default, Clone)]
pub struct JsxNoScriptUrl(Box<JsxNoScriptUrlConfig>);

#[derive(Debug, Default, Clone)]
pub struct JsxNoScriptUrlConfig {
    include_from_settings: bool,
    components: FxHashMap<String, Vec<String>>,
}

#[derive(Debug, Default, Clone, Deserialize)]

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Replace the javascript: URL with a real handler: <button onClick={...}> or <a href="#" onClick={e => { e.preventDefault(); fn(); }}>
  2. If the element only triggers behavior, change the tag to <button type="button"> for correct semantics and a11y
  3. Register custom link components/props via the rule's components config or linkComponents settings so their URLs are validated too
  4. Search the codebase for obfuscated variants (mixed case, embedded whitespace) — the regex catches them, so trust the linter over a plain grep

Example fix

// before
<a href="javascript:void(0)" onClick={open}>Open</a>

// after
<button type="button" onClick={open}>Open</button>
Defensive patterns

Strategy: validation

Validate before calling

npx oxlint -D react/jsx-no-script-url src/  # also run a security review on link attributes

Prevention

When it happens

Trigger: href="javascript:void(0)" or javascript:-prefixed values on <a>, plus custom link components/props configured via the rule's components option or settings linkComponents (includeFromSettings). React 19 upgrade audits where legacy javascript: hrefs now throw at runtime.

Common situations: Legacy codebases with <a href="javascript:void(0)" onclick=...> patterns pre-React-16; upgrading to React 19 where such URLs are hard-disallowed and crash rendering; link-like custom components (<Link to=...>, <NavLink href=...>) that need to be registered in settings so their URL props are checked.

Related errors


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