A code review shows a SQL query built by concatenating user input. What's the correct fix?
Short answer
Parameterized queries are the actual fix: they separate code from data so user input is always treated as a value, never as SQL that can change the query's structure. Manual escaping is error-prone and bypassable across encodings and dialects. A WAF is a compensating control, not a fix, and encoding tricks defeat it. A length check doesn't stop injection at all. Fix it at the query layer.
A query assembled with string concatenation lets attacker-controlled text become part of the SQL the database parses. The root cause is that code and data are mixed in the same string. Any fix that doesn't separate them is treating symptoms.
Why parameterized queries are the fix
With a prepared statement, the SQL text with placeholders is sent to the database and compiled first; the user values are sent separately and bound to those placeholders. The parser has already decided the query's structure before it ever sees the input, so a value like ' OR 1=1-- can only ever be a string literal — never new SQL syntax. This is structural, not a filter you have to keep tuning, which is why it is the canonical OWASP recommendation.
Why the other options fail
- Escaping quotes with a regex tries to neutralize dangerous characters by hand. It breaks on alternate encodings, Unicode, numeric contexts that need no quotes, and the subtle escaping differences between MySQL, PostgreSQL, and others. One missed context reopens the hole.
- Adding a WAF rule and leaving the code as-is is a compensating control, useful as defense-in-depth, but it pattern-matches traffic and is routinely bypassed with comments, case changes, and encoding. The vulnerable code still ships.
- A 100-character length check does nothing:
' OR 1=1--and most exfiltration payloads fit comfortably under any reasonable limit.
What the interviewer is probing
They want to see that you fix the class of bug at the right layer rather than reaching for a filter or an appliance. A strong answer names parameterization first, treats input validation and a WAF as additional layers (never the fix), and knows the edge case: bind variables can't parameterize identifiers like table or column names, so dynamic schema elements must instead be validated against a strict allow-list.
Likely follow-ups
- How do parameterized queries actually prevent the parser from treating input as code?
- Where do prepared statements NOT help — for example, dynamic table or column names?
- How would you roll this fix out safely across a large legacy codebase?