Understanding SQL Injection and How to Prevent It
How SQL Injection actually works, why it's dangerous, and why prepared statements are the only reliable defense — based on OWASP's own guidance.

What Is SQL Injection?
SQL Injection remains one of the oldest and most common web security vulnerabilities. As OWASP defines it, the attack happens when untrusted input is inserted into a SQL query without proper validation, letting an attacker alter the query's logic.
The root problem is that SQL makes no real distinction between "command" and "data." If a form concatenates raw input into a query like:
SELECT * FROM items WHERE owner = 'user' AND itemname = 'name'
and an attacker submits name' OR 'a'='a' instead of a real item name, the query becomes:
SELECT * FROM items WHERE owner = 'user' AND itemname = 'name' OR 'a'='a'
Since 'a'='a' is always true, the WHERE clause is effectively neutralized and every row is returned. More advanced variants chain multiple statements together (for example appending ; DELETE FROM items; --) to modify or destroy data outright.
Why It's Dangerous
A successful SQL injection can:
- Expose confidential data such as passwords or payment details
- Modify or delete records
- Bypass authentication entirely
- In the worst case, escalate to full database administrator access
OWASP classifies this class of attack as high severity, both because of how common it still is and because of how directly it touches raw data.
The Real Fix: Prepared Statements
The only reliable defense is to fully separate "command" from "data" using parameterized queries (prepared statements). Instead of splicing user input into the query text, the value is sent to the database as a separate parameter, and the database never interprets it as part of the SQL command itself.
If you're using an ORM like Prisma (as this project does), that protection is on by default:
await prisma.user.findFirst({
where: { email: userInput },
});
Under the hood, Prisma builds a parameterized query, so user input is never concatenated directly into raw SQL.
Defense in Depth
Parameterized queries are enough on their own, but these additional layers make the system more resilient:
- Least privilege: the database account your app connects with should only have the permissions it actually needs.
- Input validation: constraining input format is a helpful extra layer, not a replacement for parameterized queries.
- Web Application Firewalls (WAF): useful for filtering known attack patterns, but bypassable and should never be the only line of defense.
Takeaway
SQL Injection is a fully preventable vulnerability. Consistently using prepared statements or a trustworthy ORM, combined with least-privilege database access, effectively eliminates this entire class of attack.



