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 doesView on GitHub (pinned to e1e7af627c)
Solutions
- Replace eval of JSON text with `JSON.parse`.
- Replace dynamic member access with bracket notation: `obj[key]` instead of `eval('obj.' + key)`.
- For real code generation, use `new Function(...)` with strict inputs, or a small expression library.
- 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
- Treat each eval as a security review item; log and justify it.
- Use JSON.parse for data and bracket access for lookups.
- Serve a CSP header without 'unsafe-eval' so the browser blocks it too.
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
- Implied eval. Consider passing a function instead of a strin
- Implied eval. Do not use execScript().
- `debugger` statement is not allowed
- Variables should not be deleted
- A regular expression literal can be confused with '/='.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/12871c65fa6b6d6d.
Report an issue: GitHub.