flawopen.com/Reference/MongoDB NoSQL Injection
MongoDB NoSQL Injection: when input changes a query
MongoDB does not execute SQL, so SQL-string concatenation is not the issue. An application can still create a NoSQL injection flaw when it accepts an untrusted nested object where it expects a scalar and passes that object into a MongoDB filter. This is an application input-validation bug, not a MongoDB server CVE.
Plain English: a value becomes a rule
Imagine a form asks for a person’s name, but the clerk accepts a whole set of filing instructions in that box. The database then follows the instructions instead of comparing one name. Validate that the box contains the expected kind of value, and build the search rule yourself.
The trust boundary: request JSON to MongoDB filter
- Query filter
- A BSON document that MongoDB interprets as field comparisons and, when explicitly present, query operators.
- Operator injection
- An application passes attacker-controlled structure into a filter position where it intended one literal value.
- Scalar validation
- Checking the input type, length, and allowed format before it can influence a database operation.
- Projection
- A server-selected list of fields returned from a query, which limits accidental data exposure.
How the failure happens
The endpoint expects a scalar
The API contract says a field such as username is one string, but a JSON parser can represent strings, arrays, objects, booleans, and null.
The application skips type validation
The handler inserts the parsed value directly into a server-created filter, so an object remains structured query data rather than being treated as a literal string.
MongoDB evaluates the supplied structure
If the nested document contains query-operator structure, the predicate can mean something different from the intended exact-value comparison. The affected records depend on the query and the application’s authorization checks.
The response determines the exposure
Returned fields and record counts depend on projection, endpoint behavior, and the database account’s privileges. This does not by itself prove authentication bypass or database-wide access.
MongoDB’s official driver guidance documents this boundary when an endpoint converts unvalidated JSON to BSON and uses it as a filter. This guide models that application-level failure. It does not claim every MongoDB deployment is vulnerable, identify a server CVE, or provide an authentication-bypass recipe.
Vulnerable and hardened Node.js patterns
app.post("/users/lookup", async (req, res, next) => {
try {
// The route expects a string, but req.body.username is untrusted JSON.
const user = await users.findOne({ username: req.body.username });
res.json(user ? { username: user.username } : null);
} catch (error) {
next(error);
}
});
const loginSchema = z.object({
username: z.string().trim().min(1).max(128),
password: z.string().min(1).max(1024)
}).strict();
app.post("/login", async (req, res, next) => {
try {
const parsed = loginSchema.safeParse(req.body);
if (!parsed.success) return res.sendStatus(400);
const { username, password } = parsed.data;
// The application owns the filter key; input supplies only a string value.
const user = await users.findOne(
{ username },
{ projection: { _id: 1, username: 1, passwordHash: 1 } }
);
const passwordMatches = user &&
await argon2.verify(user.passwordHash, password);
if (!passwordMatches) return res.sendStatus(401);
return res.sendStatus(204); // Session creation is application-specific.
} catch (error) {
next(error);
}
});
The hardened path rejects non-string fields before database access, accepts no client-supplied filter object, constructs a fixed filter key in application code, returns only selected fields, and verifies a password hash after looking up the user. The snippet assumes z is Zod, users is the MongoDB collection, and argon2 is a configured password-hashing library; session handling is intentionally outside the example.
Verification checks for the fix
- ✓Send a normal string and confirm the handler queries only the exact application-owned field.
- ✓Send an object, array, number, boolean, null, missing field, oversized string, and unknown property; assert the schema rejects invalid shapes before MongoDB is called.
- ✓Assert the database call receives a filter built by the server, never a client-provided filter or raw JSON fragment.
- ✓Verify the response projection excludes password hashes and unrelated fields, and the application database role has only required collection permissions.
- ✓Hash passwords with Argon2id or bcrypt and verify hashes in application code; never query MongoDB using a submitted password as a filter.
Primary sources
- MongoDB — Client Libraries Best Practices: validate untrusted input before converting JSON to BSON
- OWASP — NoSQL Security Cheat Sheet
- MongoDB — Create a Query Filter (C# Driver): validation is the application’s responsibility