oxc-project/oxc · warning

eval can be harmful.

Error message

eval can be harmful.

What it means

This diagnostic comes from the `no_eval` rule in oxlint. It reports references to `eval`, because `eval()` runs a string as code: it can execute injected input, blocks engine optimization, and breaks scope rules. Direct calls, aliases such as `const foo = eval; foo(code)`, and indirect forms like `(0, eval)(code)` or `window.eval(code)` are reported. The option `allowIndirect` (default `false`) stops reports on the indirect forms when set to `true`; a local or member `eval` that shadows the global is not reported.

Source

Thrown at crates/oxc_linter/src/rules/eslint/no_eval.rs:17

use oxc_ast::AstKind;
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};
use schemars::JsonSchema;
use serde::Deserialize;

use crate::{
    AstNode,
    ast_util::{self},
    config::GlobalValue,
    context::LintContext,
    rule::{DefaultRuleConfig, Rule},
};

fn no_eval_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("eval can be harmful.")
        .with_help("Avoid eval(). For JSON parsing use JSON.parse(); for dynamic property access use bracket notation (obj[key]); for other cases refactor to avoid evaluating strings as code.")
        .with_label(span)
}

#[derive(Debug, Default, Clone, JsonSchema, Deserialize)]
#[serde(rename_all = "camelCase", default, deny_unknown_fields)]
pub struct NoEval {
    /// This `allowIndirect` option allows indirect `eval()` calls.
    ///
    /// Indirect calls to `eval`(e.g., `window['eval']`) are less dangerous
    /// than direct calls because they cannot dynamically change the scope.
    /// Indirect `eval()` calls also typically have less impact on performance
    /// compared to direct calls, as they do not invoke JavaScript's scope chain.
    allow_indirect: bool,
}

declare_oxc_lint!(
    /// ### What it does

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Replace eval of JSON text with `JSON.parse`.
  2. Replace dynamic member access with bracket notation: `obj[key]` instead of `eval('obj.' + key)`.
  3. For real code generation, use `new Function(...)` with strict inputs, or a small expression library.
  4. Set `"allowIndirect": true` for intentional indirect eval, or disable per line with `// oxlint-disable-next-line no-eval`.

Example fix

// before
const data = eval('(' + serverJson + ')');

// after
const data = JSON.parse(serverJson);
Defensive patterns

Strategy: validation

Validate before calling

// reject any eval reference before lint
if (/\beval\s*\(/.test(src) || /\beval\b/.test(src)) throw new Error('eval reference found');

Prevention

When it happens

Trigger: A direct call `eval(userInput)`. An alias `const foo = eval;` followed by `foo(code)`. An indirect call `(0, eval)(code)` or `this.eval(code)` in non-class code, reported while `allowIndirect` is `false`. The rule checks root unresolved references to the `eval`, `global`, `window`, and `globalThis` globals.

Common situations: Legacy code evaluates JSON or templates received from a server. Dynamic expression filters are copied from old examples. A security review turns the rule on, and old code lights up in CI.

Related errors


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