oxc-project/oxc · warning · OxcDiagnostic

Unexpected `javascript:` url

Error message

Unexpected `javascript:` url

What it means

oxlint's `no-script-url` rule. It flags any string literal that starts with `javascript:` (case-insensitive, via `starts_with_ignore_case`), the URI scheme that executes its body as script. Such URLs are an XSS vector and break CSPs that forbid inline script. The help text says to execute the code directly.

Source

Thrown at crates/oxc_linter/src/rules/eslint/no_script_url.rs:9

use oxc_ast::AstKind;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

use crate::{AstNode, context::LintContext, rule::Rule, utils::starts_with_ignore_case};

fn no_script_url_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Unexpected `javascript:` url")
        .with_help("Execute the code directly instead.")
        .with_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct NoScriptUrl;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Disallow `javascript:` URLs.
    ///
    /// ### Why is this bad?
    ///
    /// Using `javascript:` URLs is considered by some as a form of `eval`. Code
    /// passed in `javascript:` URLs must be parsed and evaluated by the browser
    /// in the same way that `eval` is processed. This can lead to security and
    /// performance issues.

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Call the function directly: `onclick="doThing()"` in markup or `addEventListener` in script.
  2. Use `href="#"` with `event.preventDefault()` for placeholder links.
  3. For `javascript:void(0)` no-ops, use a `<button type="button">` instead.

Example fix

// before
const link = `<a href="javascript:void openHelp()">Help</a>`;

// after
const link = `<button type="button" onclick="openHelp()">Help</button>`;
Defensive patterns

Strategy: validation

Validate before calling

// Detect javascript: URLs in any string, case-insensitively (mirrors starts_with_ignore_case)
function hasScriptUrl(src) {
  return /['"`]\s*javascript\s*:/i.test(src);
}

Type guard

function isScriptUrl(value) {
  return /^\s*javascript\s*:/i.test(String(value));
}
// guard before assigning hrefs:
if (!isScriptUrl(url)) link.setAttribute('href', url);

Prevention

When it happens

Trigger: `location.href = "javascript:alert('hi')";`, `el.setAttribute('href', 'JavaScript:void(0)')`, `const url = 'javascript:doThing()'` — any StringLiteral whose text begins with the scheme in any casing.

Common situations: Legacy `href="javascript:void(0)"` placeholders in templates; bookmarklet-style navigation; CSP violations surfacing after enabling strict Content-Security-Policy.

Related errors


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