In short
One badly built query and a stranger can read your whole users table by typing a few quote marks into the login box. The fix is boring, simple and non-negotiable.
An attack where malicious input is crafted to alter your SQL query's meaning — one of the oldest and still most damaging vulnerabilities, entirely preventable with parameterized queries.

Think of it like this
The bank slip with extra instructions
A clerk who blindly follows whatever is written on a deposit slip is a disaster. Someone writes 'Name: Ravi, and also hand me every account's balance' in the name box. A sensible clerk treats the name box as just a name. Parameterised queries make your database that sensible clerk.
Watch it happen
One login box, two very different queries
email: ' OR '1'='1
1/5The attacker types a quote and a condition that is always true into the email field.
The big ideas
What you need to know
Data became code
Injection happens when user input is mixed into a command string, so the database can't tell your SQL from theirs.
Placeholders fix it
With $1 or ?, the query shape is fixed first. The value is sent separately and is never parsed as SQL.
ORMs help, mostly
Prisma, Drizzle and Sequelize use parameters by default. Their raw-query escape hatches can still be misused.
Least privilege
Your app's database user shouldn't be allowed to drop tables. If something slips through, damage stays small.
See it in code
Walk through the code
1import { Pool } from "pg";2const pool = new Pool();3 4// Dangerous: user input becomes part of the SQL text5const bad = `SELECT * FROM users WHERE email = '${email}'`;6 7// Safe: the query and the value travel separately8const { rows } = await pool.query(9 "SELECT * FROM users WHERE email = $1",10 [email]11);1/2String interpolation pastes the raw input straight into the SQL. A single quote in email breaks out of the string.
Escaping quotes by hand is a losing game. Let the driver send parameters; it's also often faster because the database can reuse the plan.
Save yourself the pain
Common mistakes
Oops
Using prisma.$queryRawUnsafe with a template string built from user input.
Do this instead
Use the tagged prisma.$queryRaw template, which turns each interpolated value into a parameter.
Oops
Thinking input validation alone stops injection.
Do this instead
Validate, yes, but still use parameters. Validation can miss cases; placeholders don't.
Your mission
Break and fix your own query
Quick check
Which line is safe against SQL injection?
Go deeper
- 1Deliberately build a vulnerable query, then fix it with parameterized queries/prepared statements.
- 2Confirm your ORM parameterizes queries by default — most do.
- 3Never string-concatenate user input directly into a raw SQL query, no exceptions.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.