Securityerrorrecommended presetstrict preset

ai-guard/no-eval-dynamic

Blocks dynamic code execution via eval() or new Function() with unsanitized inputs

What it does

Flags calls to `eval()` or `new Function()` where the argument is not a string literal — i.e., where any variable, expression, or template literal with dynamic content is passed.

Why AI tools generate this pattern

`eval()` and `new Function()` execute arbitrary JavaScript at runtime. When the argument is user-controlled (from `req.body`, `req.query`, a database value, or any external source), this is a direct code injection vulnerability. An attacker can execute any code on your server with the same permissions as your Node.js process. AI tools sometimes generate `eval()` usage when implementing dynamic expression evaluators, template engines, or configuration parsers — because `eval` is the simplest way to run a string as code. The safer alternatives (expression parsers, sandboxed VMs, dedicated template engines) require more code.

Code Examples

Incorrect (Flagged by AI Guard)
// User-controlled input passed to eval — direct RCE vulnerability
app.post('/calculate', (req, res) => {
  const result = eval(req.body.expression); // ← arbitrary code execution
  res.json({ result });
});

// new Function with dynamic content
const fn = new Function('x', userProvidedCode); // ← code injection
fn(data);

// Template literal — still dynamic even if it looks controlled
const code = `return ${req.query.formula}`;
const fn = new Function(code); // ← flagged
Correct (Safe & Deterministic)
// Use a safe expression library instead of eval
import { evaluate } from 'mathjs';

app.post('/calculate', (req, res) => {
  try {
    const result = evaluate(req.body.expression); // sandboxed, no code injection
    res.json({ result });
  } catch {
    res.status(400).json({ error: 'Invalid expression' });
  }
});

// For template rendering, use a dedicated template engine
import { render } from 'mustache';
const output = render(template, data); // ← no eval, no injection

// Static eval is fine (literal string only, no user input)
const result = eval('2 + 2'); // ← not flagged (literal)

How to Fix

  1. For **math expressions**: use `mathjs`, `expr-eval`, or `jexl`
  2. For **template rendering**: use Mustache, Handlebars, Nunjucks, or similar
  3. For **JSON evaluation**: use `JSON.parse()` — never `eval()`
  4. For **sandboxed code execution**: use Node.js `vm.runInNewContext()` with strict resource limits

Nuances & False Positive Prevention

Legitimate usage can be exempted with inline disable comments (// ai-guard-disable-next-line no-eval-dynamic) when appropriate.

Configuration

Enable or override this rule in your ESLint configuration:

eslint.config.mjs
// eslint.config.mjs
export default [
  {
    plugins: { 'ai-guard': aiGuard },
    rules: {
      'ai-guard/no-eval-dynamic': 'error',
    },
  },
];

Related Rules