NoSQL injection: rewriting MongoDB queries from a request

NoSQL databases do not parse SQL, but they still interpret structure. A request that sends an object where you expected a string, or text that ends up inside a $where expression, changes what the query means.

Example

Vulnerable
// $where runs JavaScript inside MongoDB
allocations.find({
  $where: `this.userId == ${userId} && this.stocks > '${req.query.threshold}'`
});

// {"password": {"$ne": null}} matches any user
users.findOne({ user: req.body.user, password: req.body.password });
Fixed
const threshold = Number.parseInt(req.query.threshold, 10);
if (!(threshold >= 0 && threshold <= 99)) return res.sendStatus(400);
allocations.find({ userId, stocks: { $gt: threshold } });

users.findOne({ user: String(req.body.user) });
// then compare the password hash with bcrypt.compare

How it happens

Two shapes. $where takes JavaScript that MongoDB runs for every document, so a value such as 1'; return true; ' returns everything and a busy loop can stall the server. Operator injection is quieter: body parsers turn password[$ne]= into {"$ne": ""}, and a login query that drops the request value in unchanged then matches any account.

How to fix it

Keep request data as plain values.

  • Do not use $where; express conditions with query operators
  • Cast values to the type you expect (String, Number) before querying
  • Enable Mongoose sanitizeFilter, or strip keys starting with $ from input
  • Look users up by name, then verify the password hash separately

How RepoVerse finds it

  • HighRequest input runs inside a MongoDB `$where` expression

    `$where` is JavaScript evaluated by the database. A crafted value can return every document (`1'; return true; '`) or hang the server (`';while(true){}'`).

    data flow · CWE-943

  • ModerateRequest value used directly as a MongoDB filter value

    If the body parser accepts objects, `{"$ne": null}` or `{"$gt": ""}` in that field matches any document — the classic login bypass.

    data flow · CWE-943

Questions

Is MongoDB immune to injection because it has no SQL?
No. $where executes JavaScript, and query operators passed in from a request change which documents match. Both are classified as CWE-943.
How does RepoVerse detect NoSQL injection?
It traces request input into $where strings — including across files into a data-access layer — and flags request values used directly as filter values, which can carry operator objects.

Related

Updated 2026-10-11