Preventing SQL Injection: Never Trust User Input
To prevent SQL injection, treat SQL as a template and user input as data that can only fill placeholders, never changing the query's structure. Use this for any database query in your Node.js app that uses external data.
WHY IT EXISTS: SQL Injection exists because developers sometimes mix data with code. If user input (data) is concatenated directly into a SQL query string (code), an attacker can provide malicious input that changes the query's logic, allowing them to bypass authentication, steal data, or even destroy the database.
THE MENTAL MODEL: Think of your SQL query as a form letter with blank spaces, like "Dear ____, you have won ____ dollars!". User input is the data used to fill in those blanks. Parameterized queries ensure that the input ('John Smith', '100') can only be treated as data for the blanks, never as part of the letter's structure itself.
HOW IT WORKS: The correct defense is to use parameterized queries, also known as prepared statements. Your application sends the SQL command to the database server with placeholders (like ? or $1) instead of the actual user data. In a separate step, it sends the user's data. The database engine first parses and compiles the query's structure, then safely inserts the data into the placeholders. Because the query's logic is already locked in, the data cannot be executed as a command.
WHEN TO USE IT: Always. Every time your Node.js application constructs a SQL query that includes variable data, especially data originating from an external source like a user's browser, an API call, or a file. There is no performance penalty significant enough to justify avoiding them.
WHEN NOT TO USE IT: There is no valid reason to avoid parameterized queries when dealing with external data. Manually building queries via string concatenation is an anti-pattern. Even for dynamic queries where column or table names must change, those names should come from a hardcoded allow-list, not directly from user input.
ONE CANONICAL EXAMPLE: Imagine a user login in an Express app. The VULNERABLE way uses string concatenation: const query = "SELECT * FROM users WHERE username = '" + req.body.username + "'";. An attacker could enter ' OR '1'='1 as the username, making the query ...WHERE username = '' OR '1'='1', which is always true, bypassing the login. The SECURE way uses parameterization (e.g., with the mysql2 library): const sql = "SELECT * FROM users WHERE username = ?"; db.query(sql, [req.body.username]);. Here, the malicious input is treated as a literal string, and the database correctly finds no user with that name.
Read the original → cheatsheetseries.owasp.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.