Skip to content

Commit

Permalink
feat(linter): no_script_url (#2761)
Browse files Browse the repository at this point in the history
Rule detail: https://eslint.org/docs/latest/rules/no-script-url

---------

Co-authored-by: j.buendia <j.buendia>
  • Loading branch information
JoSeBu1 committed Mar 20, 2024
1 parent 99dcd00 commit 291dc05
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 0 deletions.
2 changes: 2 additions & 0 deletions crates/oxc_linter/src/rules.rs
Expand Up @@ -91,6 +91,7 @@ mod eslint {
pub mod no_redeclare;
pub mod no_regex_spaces;
pub mod no_return_await;
pub mod no_script_url;
pub mod no_self_assign;
pub mod no_self_compare;
pub mod no_setter_return;
Expand Down Expand Up @@ -416,6 +417,7 @@ oxc_macros::declare_all_lint_rules! {
eslint::no_redeclare,
eslint::no_regex_spaces,
eslint::no_return_await,
eslint::no_script_url,
eslint::no_self_assign,
eslint::no_self_compare,
eslint::no_setter_return,
Expand Down
99 changes: 99 additions & 0 deletions crates/oxc_linter/src/rules/eslint/no_script_url.rs
@@ -0,0 +1,99 @@
use oxc_ast::AstKind;
use oxc_diagnostics::{
miette::{self, Diagnostic},
thiserror::Error,
};
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

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

#[derive(Debug, Error, Diagnostic)]
#[error("eslint(no-script-url): Script URL is a form of eval")]
#[diagnostic(severity(warning), help("Disallow `javascript:` urls"))]
struct NoScriptUrlDiagnostic(#[label] pub 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 has to be parsed and evaluated by the browser in the same way that eval is processed.
///
/// ### Example
/// ```javascript
/// /*eslint no-script-url: "error"*/
///
/// location.href = "javascript:void(0)";
///
/// location.href = `javascript:void(0)`;
/// ```
NoScriptUrl,
style
);

impl Rule for NoScriptUrl {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
match node.kind() {
AstKind::StringLiteral(literal)
if literal.value.to_lowercase().starts_with("javascript:") =>
{
emit_diagnostic(ctx, literal.span);
}
AstKind::TemplateLiteral(literal)
if !is_tagged_template_expression(ctx, node, literal.span) =>
{
if literal.quasis.len() == 1
&& literal
.quasis
.first()
.unwrap()
.value
.raw
.to_lowercase()
.starts_with("javascript:")
{
emit_diagnostic(ctx, literal.span);
}
}
_ => {}
}
}
}

fn emit_diagnostic(ctx: &LintContext, span: Span) {
ctx.diagnostic(NoScriptUrlDiagnostic(Span::new(span.start, span.end)));
}

fn is_tagged_template_expression(ctx: &LintContext, node: &AstNode, literal_span: Span) -> bool {
matches!(
ctx.nodes().parent_kind(node.id()),
Some(AstKind::TaggedTemplateExpression(expr)) if expr.quasi.span == literal_span
)
}

#[test]
fn test() {
use crate::tester::Tester;

let pass = vec![
"var a = 'Hello World!';",
"var a = 10;",
"var url = 'xjavascript:'",
"var url = `xjavascript:`",
"var url = `${foo}javascript:`",
"var a = foo`javaScript:`;",
];

let fail = vec![
"var a = 'javascript:void(0);';",
"var a = 'javascript:';",
"var a = `javascript:`;",
"var a = `JavaScript:`;",
];

Tester::new(NoScriptUrl::NAME, pass, fail).test_and_snapshot();
}
31 changes: 31 additions & 0 deletions crates/oxc_linter/src/snapshots/no_script_url.snap
@@ -0,0 +1,31 @@
---
source: crates/oxc_linter/src/tester.rs
expression: no_script_url
---
eslint(no-script-url): Script URL is a form of eval
╭─[no_script_url.tsx:1:9]
1var a = 'javascript:void(0);';
· ─────────────────────
╰────
help: Disallow `javascript:` urls

eslint(no-script-url): Script URL is a form of eval
╭─[no_script_url.tsx:1:9]
1var a = 'javascript:';
· ─────────────
╰────
help: Disallow `javascript:` urls

eslint(no-script-url): Script URL is a form of eval
╭─[no_script_url.tsx:1:9]
1var a = `javascript:`;
· ─────────────
╰────
help: Disallow `javascript:` urls

eslint(no-script-url): Script URL is a form of eval
╭─[no_script_url.tsx:1:9]
1var a = `JavaScript:`;
· ─────────────
╰────
help: Disallow `javascript:` urls

0 comments on commit 291dc05

Please sign in to comment.