Eval Injection
debt(d5/e3/b3/t9)
Closest to 'specialist tool catches it' (d5). The term's detection_hints.tools list phpstan, psalm, and semgrep — all specialist static analysis tools. The pattern (eval( with variable interpolation) is automatable but requires these dedicated tools; no default linter catches it, and it won't surface as a compiler error.
Closest to 'simple parameterised fix' (e3). The quick_fix states: remove eval() entirely and replace with a data-driven strategy pattern. This is typically a contained refactor within one component — swapping eval() calls for a lookup table or callback dispatch — not a cross-cutting architectural change. Slightly above e1 because the replacement requires a small design choice (strategy pattern) rather than a single-line swap.
Closest to 'localised tax' (b3). The applies_to scope is web and CLI contexts, but eval() usage tends to be localised to specific callsites rather than load-bearing across the whole codebase. Once removed, the rest of the codebase is unaffected. It doesn't impose a persistent structural tax on future maintainers beyond the callsite itself.
Closest to 'catastrophic trap — the obvious way is always wrong' (t9). The misconception field explicitly states: 'eval() is safe if you sanitise the input first. Sanitising code intended for eval() is an arms race you will lose.' This is exactly the t9 pattern: the intuitive mitigation (sanitisation) is not merely insufficient but fundamentally the wrong mental model. Competent developers routinely believe sanitisation solves the problem, making the trap catastrophic.
Also Known As
TL;DR
Explanation
eval() executes a string as PHP code at runtime. If any part of that string is user-controlled, the attacker can execute arbitrary PHP — read files, run system commands, exfiltrate environment variables, or install a web shell. There is no safe way to pass user input to eval(); the only fix is to remove eval() and redesign the feature using whitelists, expression parsers, or template engines.
How It's Exploited
# eval() executes arbitrary PHP → remote code execution
Common Misconception
Why It Matters
Common Mistakes
- Using eval() for any dynamic behaviour that could be achieved with a lookup table, strategy pattern, or callbacks.
- Trusting 'sanitised' input — there is no safe way to sanitise PHP code for eval().
- Using the deprecated preg_replace() /e modifier which implicitly called eval().
- Template engines that fall back to eval() for dynamic expressions without sandboxing.
Code Examples
// eval() with user input — direct code execution
$formula = $_GET['formula'];
eval("$result = $formula;");
// ?formula=system('cat /etc/passwd')// → RCE
// Never pass user input to eval()
// For math expressions, use a safe parser library:
use NXP\MathExecutor;
$calc = new MathExecutor();
$result = $calc->execute($_GET['formula']); // sandboxed math only
// Or whitelist the allowed operations:
$allowed = '/^[\d\s+\-*\/().]+$/';
if (!preg_match($allowed, $_GET['formula'])) abort(400);
// Even then, avoid eval — prefer a real expression parser