Prevent injection by keeping untrusted data separate from commands. Use a safe API that parameterizes the call first, then allow-list validation for parts that cannot be parameterized, then escaping only as a last resort. Filters and error hiding are not defenses on their own.
What injection is
OWASP's A05:2025 entry defines an injection flaw as one that lets untrusted user input be sent to an interpreter, such as a browser, database or command line, which then runs parts of that input as commands. It applies when data is not validated or sanitized, when dynamic queries are built from user data without context-aware escaping, or when hostile data is concatenated into a query or command.
The same pattern covers SQL, operating system commands, template engines, LDAP, XML and the browser itself, where it shows up as cross-site scripting.
The four defenses, strongest first
| Order | Defense | Use it for | Weakness |
|---|---|---|---|
| 1 | Safe API or parameterized interface | Values in queries and commands | Stored procedures can still be injectable if they build queries by concatenation |
| 2 | Allow-list input validation | Parts that cannot be bound, such as table names, column names and sort direction | Not complete where free text must be allowed |
| 3 | Context-aware output encoding | Data going into HTML, attributes, JavaScript and URLs | Needs the right encoder for each context |
| 4 | Escaping input for the interpreter | Legacy code where nothing else is practical | Described by OWASP as frail and error-prone |
1. Safe API. The A05 guidance says the preferred option is an API that avoids the interpreter, provides a parameterized interface, or uses an object relational mapper. In the OWASP SQL cheat sheet, prepared statements mean that even if an attacker types a quote and an always-true condition, the database treats the whole string as a literal value. It notes that stored procedures offer the same protection only when they do not build queries from strings with dynamic execution.
2. Allow-list validation. Bind variables cannot stand in for table names, column names or the ASC and DESC sort word. The guidance there is to take such values from code, or map user input to a fixed list of legal values. For commands, an allow-list pattern such as lowercase letters and digits within a set length excludes shell metacharacters entirely.
3. Output encoding. For cross-site scripting, the strongest defense is context-sensitive output encoding, with validation as a supporting layer. See output encoding by context.
4. Escaping. The SQL cheat sheet says to use this only as a last resort, when nothing above is feasible, mainly to retrofit legacy code. The A05 guidance warns these techniques involve parsing and escaping complex strings and are error-prone when the underlying system changes. It also notes that SQL structure names cannot be escaped, which is a common problem in report-writing software.
Common mistakes
- Treating input validation as the whole defense, then allowing special characters because users need them.
- Trusting an ORM and then writing raw string queries inside it. OWASP's own scenario shows a Hibernate query built by concatenation that is still injectable.
- Building command lines from strings and passing them to a shell, rather than passing an argument list to a program. See avoiding the shell.
- Hiding error messages and calling it fixed.
How scanners fit in
Static analysis finds concatenation into queries and commands in code. A dynamic scan sends probe values and watches behavior, which confirms a flaw is reachable on a live system. Neither replaces the design rule above. If a finding appears, fix the construction, not just the value that triggered it, and write a regression test using the same input. Our post on how to retest an injection finding shows the steps.
Try it yourself
Click through it at your own pace, or open it full screen. Look for findings where a value flows from a request into a query or command.
Quick check
Is input validation enough to stop SQL injection?
Not on its own. OWASP calls it useful but not a complete defense. Parameterized queries are the primary control, with validation for the parts that cannot be bound.
Do ORMs make injection impossible?
No. Concatenating user input into an ORM's query language can still be injectable.
Safeguard offers a free scan at gold.safeguard.sh/scan for the libraries your data access layer depends on.
Sources
- OWASP Top 10 2025: A05 Injection
- OWASP Injection Prevention Cheat Sheet
- OWASP Query Parameterization Cheat Sheet
Last reviewed: 19 October 2026.