SQL injection is a vulnerability where user input is placed directly into a database query, so an attacker can send input that changes what the query does. Instead of being treated as data, their input becomes part of the SQL, letting them read data they should not see, bypass logins, or delete records. The fix is to use parameterized queries.
How it happens
When a query is built by concatenating or interpolating user input, like "SELECT * FROM users WHERE email = '" + email + "'", an attacker can supply input like ' OR '1'='1 that changes the query's logic. The database has no way to tell the intended query from the injected part.
The fix: parameterized queries
Pass user values as bound parameters, so the database always treats them as data and never as SQL. Most ORMs and query builders do this for you. The rule is simple: never build a query by gluing request data into the query string.
What this means for AI-generated code
AI assistants often build queries with string interpolation because it reads cleanly and returns the right rows in testing, which is exactly why the injection risk survives review. If user input can reach a query that is built by concatenation, treat it as injectable.
Common questions
How do I tell if my code is vulnerable to SQL injection?
Look for any database query where a string variable from user input is inserted directly, using + or template literals. If you see code like db.query('SELECT * FROM users WHERE id = ' + req.params.id), that is injectable. Every input that goes into a query should be a bound parameter, never part of the query string itself.
Does using an ORM prevent SQL injection?
Usually yes, if you use it correctly. ORMs that generate queries from method calls and field assignments do not build SQL strings from input. The risk returns when you drop to a raw query and still interpolate user input — most ORMs support raw queries and those require the same parameterization care.
Can an AI-generated app have SQL injection even though it uses Supabase?
Yes. Supabase's client library uses parameterized queries when you use the standard .select() and .eq() methods, but if the app uses Supabase's rpc() method or constructs a raw Postgres query, the injection risk is the same as any other database client.