Course contentsShow
← Node.js
Lesson 1797 of 1,98016. Security Hardening and Threat MitigationFree lesson

Database Interaction Security

Implement parameterized queries to eliminate SQL and NoSQL injection vulnerabilities.

In this lesson, you will learn how to leverage parameterized queries to neutralize SQL and NoSQL injection attacks at the database driver level.

The Mechanism of Injection

Injection vulnerabilities occur when user-supplied input is treated as part of the database command rather than as literal data. For instance, if you manually concatenate a string to form a SQL query, a malicious user could input ' OR '1'='1 to bypass authentication or drop tables. This happens because the database engine cannot distinguish between your intended instructions and the malicious input.

Parameterization: Separating Code from Data

The definitive defense against this is the use of parameterized queries (often called prepared statements). Instead of building a query string with user input, you use placeholders (like ?, $1, or :name) in your query template.

When you execute the query, you pass the user input as a separate array or object. The database engine receives the query structure first, parses it, and then treats the supplied parameters strictly as data values. Because the database engine has already "compiled" the logic, the input cannot change the meaning of the query, regardless of what characters it contains.

Example in Node.js (using pg)

const query = 'SELECT * FROM users WHERE email = $1 AND status = $2';
const values = [userInputEmail, 'active'];

// The driver ensures the input is treated as a safe parameter
const result = await client.query(query, values);

Extending to NoSQL

While many focus on SQL, NoSQL databases (like MongoDB) are equally vulnerable if you pass raw objects from req.body directly into queries. For example, passing req.body.password directly might allow a user to inject a query operator like {"$gt": ""} to bypass password checks. Always explicitly define the structure of your filter objects and utilize the driver's built-in parameterization or validation methods to ensure input is typed correctly before it reaches the database layer.

By forcing a strict separation between command logic and user-supplied data, you effectively strip attackers of their ability to manipulate your database schema or access unauthorized records.

Key Takeaway: Always use parameterized queries or driver-level placeholders to treat all external input as literal data, rendering injection attempts harmless.