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
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
| Framework | Controls |
|---|---|
| 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.