CWE-94CriticalMITRE entry

Code Injection

Improper Control of Generation of Code (Code Injection)

What it is

CWE-94 exists when an application takes user input and treats it as code that the application then executes. Unlike OS command injection (which targets a shell), code injection targets the application's own interpreter: JavaScript eval, Python exec, Ruby eval, PHP eval, or any dynamic code path that compiles or evaluates strings at runtime.

Why it matters

Code injection grants remote code execution with the privileges of the application itself, with no intermediate shell to bypass. The pattern recurs in expression evaluators, formula calculators, template engines, plugin systems, and ad-hoc REPLs exposed to web users. Even where eval is not used directly, dynamic-import, Function constructor, indirect VM access (node:vm), and template strings with unescaped substitution can each be a code injection vector.

Common patterns

  • eval(req.body.expr) or eval(req.query.code) anywhere in a request handler.
  • new Function(userInput) to dynamically compile user-supplied code.
  • Python exec or compile on data from a request, message queue, or database.
  • Template engines used in eval-like mode (Jinja2 with autoescape disabled, server-side eval-style template tags).
  • node:vm Script with un-vetted user input (sandbox escapes are common).
  • JSON parsers implemented via eval (legacy code; CWE-915 overlap).

Languages affected

JavaScriptTypeScriptPythonRubyPHP

What Deva detects

Deva flags every call site that uses eval, new Function, setTimeout/setInterval with string arguments, node:vm.Script, node:vm.runInThisContext, Python exec, Python compile, Ruby instance_eval, Ruby class_eval, and PHP eval where the source data traces back to untrusted input. The scanner distinguishes safe constant-string uses (which it ignores) from variable-string uses (which it reports).

Example

Vulnerable

app.post('/calc', (req, res) => {
  const result = eval(req.body.expr)
  res.json({ result })
})

Fixed

import { Parser } from 'expr-eval'

const calculator = new Parser({
  operators: {
    add: true, subtract: true, multiply: true, divide: true,
    power: true, conditional: false, logical: false, comparison: false,
  },
})

app.post('/calc', (req, res) => {
  try {
    const expr = String(req.body.expr || '').slice(0, 100)
    const result = calculator.parse(expr).evaluate()
    if (typeof result !== 'number' || !isFinite(result)) {
      return res.status(400).json({ error: 'Bad expression' })
    }
    res.json({ result })
  } catch {
    res.status(400).json({ error: 'Bad expression' })
  }
})

Explanation

The vulnerable version eval()s a request body. An attacker posting { expr: 'require("child_process").execSync("id")' } gets remote code execution. The fix uses expr-eval, a parser that supports a strict subset of arithmetic operators with no access to JavaScript globals. The input is also length-bounded and the result is type-checked. The pattern generalizes: never eval user input, always use a domain-specific parser with an explicit grammar.

Where this fits in OWASP Top 10

Compliance framework mapping

FrameworkControls
OWASP Top 10 (2021)
A03:2021 Injection
NIST 800-53 Rev 5
SI-10 Information Input ValidationSC-18 Mobile Code
PCI-DSS v4.0
6.2.4 Software engineering techniques
CMMC 2.0 L2
SI.L2-3.14.1 Flaw remediation

Related CWEs

Deva detects CWE-94 alongside 970+ other CWE patterns at write time, with AI-assisted fix generation that maintains compliance.