← All fixes

Fix it

SQL built with string concatenation — how to fix the injection risk

High severityCWE-89 (SQL Injection)

When user input is concatenated or interpolated directly into a SQL string, an attacker can supply input that changes the query's meaning, reading or destroying data they were never allowed to touch. The fix is to pass user values as bound parameters so the database treats them as data, never as SQL.

Why it's a problem

A single injectable query can expose your entire database. Input like ' OR '1'='1 turns a login check into one that always passes, and more elaborate payloads can dump other tables, modify records, or drop them. Because the query still works for normal input, the bug often ships unnoticed until someone probes it.

The pattern

// user input becomes part of the SQL text
const q = "SELECT * FROM users WHERE email = '" + email + "'";
db.query(q);

The fix

// the value is bound as a parameter, never parsed as SQL
db.query("SELECT * FROM users WHERE email = $1", [email]);

// most ORMs parameterize for you
await prisma.user.findUnique({ where: { email } });

Why AI tools write this

Template literals make interpolating a variable into a query string the most natural-looking way to write it, so an assistant building a quick data-access helper will often concatenate the value rather than parameterize it. The result reads cleanly and returns the right rows in testing, which is exactly why the injection risk survives review.

The quick fix

  • Use parameterized queries (bound parameters) for every value that comes from a request.
  • Prefer an ORM or query builder that parameterizes by default.
  • Never build a query by concatenating or interpolating request data into the SQL string.

Want to know if this pattern is already in a repo you shipped? Scan a public repo free, no account needed.

Scan a repo →
SQL String Concatenation Injection — The Fix (Parameterized Queries): Prbl