CWE-95: Eval Injection
Overview
Eval Injection occurs when untrusted input is passed to dynamic code execution functions (such as eval, exec, or similar), allowing attackers to execute arbitrary code within the application context. Untrusted input can originate from HTTP requests, external APIs, databases, files, message queues, or any source outside the application's control.
OWASP Classification
A05:2025 - Injection
Risk
Critical: Attackers can execute arbitrary commands, steal data, escalate privileges, or fully compromise the application and underlying system.
Relationship to Other CWEs
- CWE-94 (Code Injection): Broader category covering all forms of dynamic code generation.
- CWE-95 (This page): Eval-specific code injection.
Remediation Steps
Core principle: Never execute dynamically generated code derived from untrusted input; eliminate eval/exec-style evaluation and replace it with safe parsers or allowlisted interpreters.
Trace the Data Path
Analyze how untrusted data reaches code execution:
- Source: Identify where untrusted data enters (user input, external files, databases, network requests, configuration)
- Data Flow: Trace how data moves through the application
- Sink: Locate code execution functions (
eval(),exec(),Function(),compile(),ScriptEngine) - Missing Protection: Identify lack of validation or use of dangerous functions
Eliminate Dynamic Code Execution (Primary Defense)
Never use eval() or similar functions with untrusted data:
- Remove completely: Refactor code to eliminate
eval,exec,Function(), etc. - Use safe alternatives: Mapping, parsing, configuration files, expression evaluators
- Replace with declarative approaches: JSON/YAML config, rule engines, template engines
Common dangerous functions to eliminate:
- Python:
eval(),exec(),compile(),__import__() - JavaScript:
eval(),new Function(),setTimeout(string) - PHP:
eval(),assert(),create_function() - Java:
ScriptEngine.eval(), reflection with untrusted input
Why this works: If no dynamic code execution exists, code injection is impossible.
Use Safe Alternatives
Replace code execution with safer approaches:
For mathematical expressions:
- Use safe expression evaluators (math.js, expr-eval)
- Parse to AST and allowlist operators
- Use operator mapping (map "+" to addition function)
For configuration/logic:
- JSON/YAML configuration files
- Rule engines (Drools, Easy Rules)
- Strategy pattern with pre-defined implementations
- Template engines with auto-escaping
For dynamic dispatch:
- Switch/case statements with enumerated options
- Command pattern with registered handlers
- Plugin systems with sandboxing
If Execution Unavoidable: Sandbox and Restrict
Only if absolutely required (last resort):
- Run in isolated process: Separate process with no network/filesystem access
- Implement strict timeouts: Prevent DoS (milliseconds, not seconds)
- Memory limits: Restrict resource consumption
- Allowlist operations: Only permit specific functions/modules
- Use sandboxing libraries: vm2 (Node.js), RestrictedPython, GraalVM
Critical: Sandboxing is defense-in-depth. Prefer elimination.
Add Input Validation (Defense in Depth Only)
If sandboxing is used, add validation:
- Length limits: Prevent DoS
- Character allowlist: Alphanumeric + specific allowed chars only
- Denylist dangerous keywords:
eval,exec,import,system, etc. - AST parsing: Detect dangerous constructs before execution
Warning: Validation alone is INSUFFICIENT. Bypasses are common. Use WITH sandboxing, never instead.
Test Thoroughly
Verify your fixes:
- Test code injection:
__import__('os').system('whoami'),eval('malicious') - Test object access:
constructor.constructor('return process')() - Test import injection:
require('child_process').exec('ls') - Test encoding bypasses:
\x5f\x5fimport\x5f\x5f, Base64-encoded payloads - Ensure legitimate functionality works
- Re-scan with security scanner
Common Vulnerable Patterns
- Passing untrusted input to
eval,exec, or similar functions - Using dynamic code execution for configuration or logic
Language-Specific Code Examples
For detailed, production-ready code examples in your programming language, see:
- Python - Safe expression evaluation with AST, operator mapping, secure configuration, and alternatives to eval/exec/pickle
- Java - Safe alternatives to ScriptEngine, SpEL, OGNL, reflection, and Groovy evaluation
- JavaScript/Node.js - Safe math parsers, operation mapping, controlled module loading, and CSP implementation
Each language-specific guide includes:
- Complete vulnerable and secure code patterns
- Framework-specific implementations
- Testing examples
Generic Secure Patterns
Use Explicit Operation Mapping
Replace dynamic code execution with predefined operations:
- Define an allowlist of safe operations
- Map untrusted input to pre-defined functions
- Validate all inputs before execution
- Never execute user-provided code strings
Safe Expression Evaluation
For mathematical or logical expressions:
- Use AST (Abstract Syntax Tree) parsing
- Implement a custom parser with operator allowlist
- Use well-tested libraries designed for safe evaluation
- Reject any unexpected operations or syntax
Controlled Plugin/Module Loading
For dynamic functionality:
- Maintain an explicit allowlist of approved modules
- Map untrusted input to allowlisted paths only
- Validate plugin interfaces before execution
- Never use untrusted input directly in import/require statements
Language-Specific Guidance
- Java - Avoid ScriptEngine with untrusted input, use safe alternatives
- JavaScript/Node.js - Avoid eval, use JSON.parse and safe-eval alternatives
- Python - Avoid eval/exec, use ast.literal_eval for safe parsing
Dynamic Scan Guidance
For guidance on remediating this CWE when detected by dynamic (DAST) scanners:
- Dynamic Scan Guidance - Analyzing DAST findings and mapping to source code