Injection Security Check (A05:2025)
What this checks
Protects against SQL, command, and template injection caused by passing
user-controlled data to an interpreter without sanitization. Exploitation leads to
full database read/write, remote code execution, and data exfiltration.
For NoSQL-specific injection (MongoDB operator injection, $where), see nosql-injection.
Vulnerable patterns
"SELECT * FROM users WHERE id = " + userId— user input concatenated into SQLexec("convert " + filename)— shell expansion allows; rm -rf /eval(userInput)— arbitrary code execution from user-supplied stringTemplate("Hello " + name)— template body built from user input
Fix immediately
For each vulnerable call site, apply the appropriate control:
- SQL: use parameterized queries or an ORM — never concatenate user input into query strings
- Shell: pass arguments as an array/list, never as an interpolated string — disable shell expansion
- Templates: use an engine that autoescapes by default and pass user values through the parameter interface. Python:
Environment(autoescape=True)(bool literal, notselect_autoescape()withfrom_string()). Go:html/template, nevertext/templatefor HTTP output. Java FreeMarker:cfg.setOutputFormat(HTMLOutputFormat.INSTANCE). Rust:handlebars(escapes by default). Never build the template body from user input. - eval/exec: remove entirely — there is no safe way to evaluate user-supplied code strings
Flag the vulnerable call site, explain the risk and the correct fix pattern, then continue with the original task.
Verification
Confirm the following properties hold (language-agnostic):
- User-controlled values reach SQL only as bound parameters — never via string interpolation, concatenation, or format strings
- User-controlled values reach subprocess execution only as discrete argument list elements — never via a shell string or interpolated command string
- No dynamic evaluation of user-supplied strings as code (Python
eval/exec, JSeval/new Function, etc. removed — not replaced with a safer-looking variant of the same function) - Templates use an engine where HTML autoescaping is either enabled explicitly or is the documented default (Flask
render_template, Gohtml/template, Rusthandlebars, Jinja2Environment(autoescape=True)— NOT Jinja2Template()direct, NOT Gotext/template), and user values are passed through the engine's parameter interface — never by building the template body from user input
References
- CWE-89 (SQL Injection)
- CWE-78 (OS Command Injection)
- CWE-94 (Code Injection)
- OWASP A05:2025 Injection