Overview
Injection vulnerabilities in Node.js Express apps allow attackers to modify the intended behavior of your backend by altering queries, commands, or template rendering. In practice, this can lead to unauthorized data access, data corruption, or remote code execution under certain conditions. When a backend constructs queries or shell commands by concatenating untrusted user input, an attacker can inject operators, comments, or additional statements that the application will execute.
In Express apps, these flaws appear most often when you build SQL or NoSQL queries by interpolating req.query, req.params, or req.body values into strings, or when you pass user input directly to system shells or database drivers without binding parameters. Common patterns include dynamic SQL strings, unvalidated inputs, and using powerful operators supplied by users in MongoDB queries.
Remediation focuses on preventing untrusted input from shaping command or query structure. Use parameterized queries or prepared statements, rely on ORM/ODM binding, perform strict input validation and allow-listing, avoid eval or constructing shell commands from user data, and apply least-privilege database credentials. For NoSQL, validate types and shape of queries and constrain operators; for SQL, prefer parameter binding and stored procedures where feasible; monitor and log injection attempts.
Adopt defense-in-depth: implement input validation at the edge (Express validators), enable logging and anomaly detection for unusual query patterns, and regularly update dependencies to reduce risk from known insecure components.
Code Fix Example
Node.js (Express) API Security Remediation
Vulnerable:
const username = req.body.username;
const password = req.body.password;
const sql = `SELECT * FROM users WHERE username = '${username}' AND password = '${password}'`;
const [rows] = await connection.query(sql);
Fixed:
const sql = 'SELECT * FROM users WHERE username = ? AND password = ?';
const [rows] = await connection.execute(sql, [username, password]);