From eca85410329d1c12bc0f17c707b86bc3d3fe3285 Mon Sep 17 00:00:00 2001 From: Carter Snook Date: Thu, 8 Jun 2023 21:36:12 -0500 Subject: [PATCH] feat(linter): add eslint(no-eval) (#417) --- crates/oxc_linter/src/rules.rs | 1 + crates/oxc_linter/src/rules/no_eval.rs | 67 ++++++++++++++++++++ crates/oxc_linter/src/snapshots/no_eval.snap | 40 ++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 crates/oxc_linter/src/rules/no_eval.rs create mode 100644 crates/oxc_linter/src/snapshots/no_eval.snap diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index fff5d6683..3db59a083 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -15,6 +15,7 @@ oxc_macros::declare_all_lint_rules! { no_dupe_class_members, no_empty, no_empty_pattern, + no_eval, no_new_symbol, no_self_compare, no_shadow_restricted_names, diff --git a/crates/oxc_linter/src/rules/no_eval.rs b/crates/oxc_linter/src/rules/no_eval.rs new file mode 100644 index 000000000..12df12442 --- /dev/null +++ b/crates/oxc_linter/src/rules/no_eval.rs @@ -0,0 +1,67 @@ +use oxc_ast::AstKind; +use oxc_diagnostics::{ + miette::{self, Diagnostic}, + thiserror::Error, +}; +use oxc_macros::declare_oxc_lint; +use oxc_semantic::AstNode; +use oxc_span::Span; + +use crate::{context::LintContext, rule::Rule}; + +#[derive(Debug, Error, Diagnostic)] +#[error("eslint(no-eval): eval can be harmful.")] +#[diagnostic(severity(warning))] +struct NoEvalDiagnostic(#[label("eval can be harmful")] pub Span); + +#[derive(Debug, Default, Clone)] +pub struct NoEval; + +declare_oxc_lint!( + /// ### What it does + /// Disallows referencing the 'eval' function. + /// + /// ### Why is this bad? + /// Calling 'eval' is not supported in some secure contexts and can lead to + /// vulnerabilities. + /// + /// ### Example + /// ```javascript + /// const someString = "console.log('pwned')" + /// eval(someString); + /// ``` + NoEval, + nursery +); + +impl Rule for NoEval { + fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + if let AstKind::IdentifierReference(ident) = node.get().kind() + && ident.name == "eval" + { + ctx.diagnostic(NoEvalDiagnostic(ident.span)); + } + } +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass = vec![ + ("this.eval();", None), + ("globalThis.eval();", None), + ("asdf.eval();", None), + ("const asdf = { eval: true };", None), + ]; + + let fail = vec![ + ("eval();", None), + ("eval('...');", None), + ("eval('...');", None), + ("let a = eval;", None), + ("const foo = { asdf: eval };", None), + ]; + + Tester::new(NoEval::NAME, pass, fail).test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/no_eval.snap b/crates/oxc_linter/src/snapshots/no_eval.snap new file mode 100644 index 000000000..36f57945e --- /dev/null +++ b/crates/oxc_linter/src/snapshots/no_eval.snap @@ -0,0 +1,40 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: no_eval +--- + ⚠ eslint(no-eval): eval can be harmful. + ╭─[no_eval.tsx:1:1] + 1 │ eval(); + · ──┬─ + · ╰── eval can be harmful + ╰──── + + ⚠ eslint(no-eval): eval can be harmful. + ╭─[no_eval.tsx:1:1] + 1 │ eval('...'); + · ──┬─ + · ╰── eval can be harmful + ╰──── + + ⚠ eslint(no-eval): eval can be harmful. + ╭─[no_eval.tsx:1:1] + 1 │ eval('...'); + · ──┬─ + · ╰── eval can be harmful + ╰──── + + ⚠ eslint(no-eval): eval can be harmful. + ╭─[no_eval.tsx:1:1] + 1 │ let a = eval; + · ──┬─ + · ╰── eval can be harmful + ╰──── + + ⚠ eslint(no-eval): eval can be harmful. + ╭─[no_eval.tsx:1:1] + 1 │ const foo = { asdf: eval }; + · ──┬─ + · ╰── eval can be harmful + ╰──── + +