Skip to main content
ESLint Interlace
Plugin: node-securityRules

detect-eval-with-expression

Detects eval(variable) which can allow an attacker to run arbitrary code inside your process

Keywords: eval, code injection, CWE-95, security, ESLint rule, remote code execution, RCE, arbitrary code execution, Function constructor, auto-fix, LLM-optimized, code security CWE: CWE-95
OWASP Mobile: OWASP Mobile Top 10

Detects eval(variable) which can allow an attacker to run arbitrary code inside your process. This rule is part of eslint-plugin-node-security and provides LLM-optimized error messages with fix suggestions.

🚨 Security rule | 💡 Provides LLM-optimized guidance | ⚠️ Set to error in recommended

Quick Summary

AspectDetails
CWE ReferenceCWE-95 (Code Injection)
SeverityCritical (security vulnerability)
Auto-Fix⚠️ Suggests fixes (manual application)
CategorySecurity
ESLint MCP✅ Optimized for ESLint MCP integration
Best ForAll applications, especially those handling user input

Value & investment case

Why this rule pays for itself. Framework: cicd-impact/philosophy.md.

DimensionValue
CWECWE-95 — Improper Neutralization of Directives in Dynamically Evaluated Code (eval injection)
Feedback-loop tierEditor / pre-commit (sub-second) — cheapest layer per the feedback-loop hierarchy
Defensive-layer leverage~10× cheaper than unit-test · ~1,000× cheaper than production rollback · 10,000+× cheaper than disclosureeval-injection is a Remote Code Execution class (cost-ratio anchors)
Niche relevanceCritical: infra/devtools (downstream consumers of compromised tooling), fintech, cybersecurity · High: B2B SaaS, healthtech · Medium: B2C, marketplaces
Investor-frame impactDynamic eval of user input → RCE. Single bug class that gives an attacker full process control. The single highest-payoff rule for any codebase parsing untrusted text; lint-time catch is the cheapest possible defense against the highest-cost defect class.

Read also: philosophy.md §investor-frame · niche-presets.json · analyzer-evaluation-framework.md

Vulnerability and Risk

Vulnerability: The use of eval() or similar functions (like setTimeout, setInterval, new Function) with dynamic arguments allows for the execution of arbitrary code derived from strings.

Risk: If the string passed to eval() contains user-controlled input, an attacker can execute malicious JavaScript code within the context of the application. This can lead to data theft, session hijacking, or server-side remote code execution (RCE).

Rule Details

This rule detects dangerous use of eval() and Function() constructor with dynamic expressions that can lead to remote code execution (RCE) vulnerabilities.

Error Message Format

The rule provides LLM-optimized error messages (Compact 2-line format) with actionable security guidance:

🔒 CWE-95 OWASP:A05 CVSS:9.8 | Eval Injection detected | CRITICAL [SOC2,PCI-DSS,ISO27001]
   Fix: Review and apply the recommended fix | https://owasp.org/Top10/A05_2021/

Message Components

ComponentPurposeExample
Risk StandardsSecurity benchmarksCWE-95 OWASP:A05 CVSS:9.8
Issue DescriptionSpecific vulnerabilityEval Injection detected
Severity & ComplianceImpact assessmentCRITICAL [SOC2,PCI-DSS,ISO27001]
Fix InstructionActionable remediationFollow the remediation steps below
Technical TruthOfficial referenceOWASP Top 10

Configuration

OptionTypeDefaultDescription
allowLiteralStringsbooleanfalseAllow eval with literal strings
additionalEvalFunctionsstring[][]Additional functions to treat as eval-like

Examples

❌ Incorrect

// Dynamic eval - CRITICAL risk
const result = eval(userInput);

// Function constructor - HIGH risk
const func = new Function('param', userCode);

// Template evaluation - HIGH risk
const output = eval(`Hello ${userName}!`);

// Object property access - MEDIUM risk
const value = eval(`obj.${property}`);

// Math operations - MEDIUM risk
const calc = eval(`${num1} ${operator} ${num2}`);

✅ Correct

// JSON parsing
const data = JSON.parse(userInput);

// Template literals (safe)
const greeting = `Hello ${userName}!`;

// Whitelisted object access
const ALLOWED_PROPS = ['name', 'age', 'email'];
if (ALLOWED_PROPS.includes(property)) {
  const value = obj[property];
}

// Math with validation
const result = calculate(num1, operator, num2);

// Map for dynamic storage
const config = new Map();
config.set(userKey, value);

Pattern Recognition

The rule automatically detects common eval patterns and provides targeted fixes:

JSON Parsing Pattern

❌ eval('{"key": "' + value + '"}')
✅ JSON.parse('{"key": "' + value + '"}')

Object Access Pattern

❌ eval('obj.' + property)
✅ const ALLOWED = ['name', 'age']; if (ALLOWED.includes(property)) obj[property]

Template Pattern

❌ eval('Hello ' + name + '!')
✅ `Hello ${name}!`

Math Operations Pattern

❌ eval(num1 + ' + ' + num2)
✅ const mathOps = { '+': (a, b) => a + b }; mathOps[op](num1, num2)

Security Impact

VulnerabilityCWEOWASPCVSSImpact
Code Injection95A03:20219.8 CriticalComplete server compromise
Command Injection78A03:20219.8 CriticalSystem command execution
Prototype Pollution915A01:20218.1 HighObject manipulation

Why This Matters

IssueImpactSolution
🚀 Remote Code Ex.Full server/client takeoverRemove eval() entirely; use JSON.parse or object logic
🕵️ Data InjectionManipulated business logicValidate input against a strict whitelist of allowed values
🔒 ComplianceFailure to prevent script injectionImplement Content Security Policy (CSP) and static templates

Migration Guide

Phase 1: Discovery

// Enable rule with warnings first
{
  rules: {
    'node-security/detect-eval-with-expression': 'warn'
  }
}

Phase 2: Pattern Replacement

// Replace common patterns
eval(`obj.${prop}`) → obj[prop] with validation
eval(jsonString) → JSON.parse(jsonString)
eval(mathExpr) → Safe math functions

Phase 3: Enforcement

// Strict enforcement
{
  rules: {
    'node-security/detect-eval-with-expression': 'error'
  }
}

Comparison with Alternatives

Featuredetect-eval-with-expressioneslint-plugin-securityeslint-plugin-sonarjs
Code Injection Detection✅ Yes⚠️ Limited⚠️ Limited
CWE Reference✅ CWE-95 included⚠️ Limited⚠️ Limited
LLM-Optimized✅ Yes❌ No❌ No
ESLint MCP✅ Optimized❌ No❌ No
Fix Suggestions✅ Detailed⚠️ Basic⚠️ Basic

Known False Negatives

The following patterns are not detected due to static analysis limitations:

Aliased Functions

Why: Aliased dangerous functions not traced.

// ❌ NOT DETECTED - Aliased function
const execute = eval;
execute(userInput);

Mitigation: Never alias dangerous functions.

Dynamic Invocation

Why: Dynamic method calls not analyzed.

// ❌ NOT DETECTED - Dynamic call
window['eval'](userInput);

Mitigation: Avoid dynamic method access.

Wrapper Functions

Why: Wrappers not recognized.

// ❌ NOT DETECTED - Wrapper
myEval(userInput); // Uses eval internally

Mitigation: Apply rule to wrapper implementations.

Further Reading