{"record":{"id":"13f73414faecd6a5","repo":"oxc-project/oxc","slug":"unexpected-javascript-url","errorCode":null,"errorMessage":"Unexpected `javascript:` url","messagePattern":"Unexpected `javascript:` url","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/eslint/no_script_url.rs","lineNumber":9,"sourceCode":"use oxc_ast::AstKind;\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::Span;\n\nuse crate::{AstNode, context::LintContext, rule::Rule, utils::starts_with_ignore_case};\n\nfn no_script_url_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unexpected `javascript:` url\")\n        .with_help(\"Execute the code directly instead.\")\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct NoScriptUrl;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Disallow `javascript:` URLs.\n    ///\n    /// ### Why is this bad?\n    ///\n    /// Using `javascript:` URLs is considered by some as a form of `eval`. Code\n    /// passed in `javascript:` URLs must be parsed and evaluated by the browser\n    /// in the same way that `eval` is processed. This can lead to security and\n    /// performance issues.","sourceCodeStart":1,"sourceCodeEnd":27,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/no_script_url.rs#L1-L27","documentation":"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.","triggerScenarios":"`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.","commonSituations":"Legacy `href=\"javascript:void(0)\"` placeholders in templates; bookmarklet-style navigation; CSP violations surfacing after enabling strict Content-Security-Policy.","solutions":["Call the function directly: `onclick=\"doThing()\"` in markup or `addEventListener` in script.","Use `href=\"#\"` with `event.preventDefault()` for placeholder links.","For `javascript:void(0)` no-ops, use a `<button type=\"button\">` instead."],"exampleFix":"// before\nconst link = `<a href=\"javascript:void openHelp()\">Help</a>`;\n\n// after\nconst link = `<button type=\"button\" onclick=\"openHelp()\">Help</button>`;","handlingStrategy":"validation","validationCode":"// Detect javascript: URLs in any string, case-insensitively (mirrors starts_with_ignore_case)\nfunction hasScriptUrl(src) {\n  return /['\"`]\\s*javascript\\s*:/i.test(src);\n}","typeGuard":"function isScriptUrl(value) {\n  return /^\\s*javascript\\s*:/i.test(String(value));\n}\n// guard before assigning hrefs:\nif (!isScriptUrl(url)) link.setAttribute('href', url);","tryCatchPattern":null,"preventionTips":["Use `<button type=\"button\">` for action elements instead of `<a href=\"javascript:void(0)\">`.","Attach behavior with addEventListener and keep hrefs as real URLs or `#`.","Enforce a CSP without `unsafe-inline` — it makes javascript: URLs fail loudly at runtime, complementing the lint rule."],"tags":["lint","eslint","no-script-url","security","xss","csp"],"backgroundTag":"javascript-url-xss","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}