Safeguard
Vulnerability Analysis

What is NoSQL Injection

NoSQL injection lets attackers bypass logins or run code using MongoDB operators like $ne and $where. See real CVEs, examples, and effective defenses.

Bob
Application Security Engineer
7 min read

NoSQL injection is an attack technique that manipulates queries sent to non-relational databases — MongoDB, CouchDB, Cassandra, Redis — by injecting database operators or objects instead of the string values an application expects. The classic example is a login form that builds a MongoDB query like db.users.findOne({username: username, password: password}) directly from JSON input. Send {"username": "admin", "password": {"$ne": null}} instead of a string password, and MongoDB's $ne (not-equal) operator turns the check into "find a user where the password is not null" — which is always true. No quotes, no semicolons, no classic ' OR 1=1-- syntax. The vulnerability class was formally documented by Ron and Shulman at Black Hat Europe 2012 in "A Perfect Crime? Only NoSQL Injection," and it has since produced critical, remote-code-execution-capable CVEs in real production software.

How Does NoSQL Injection Actually Work?

NoSQL injection works by exploiting the fact that NoSQL query languages accept structured objects, not just strings, so an attacker who controls JSON, form-encoded, or URL parameters can smuggle in operators the application never intended to expose. In MongoDB, operators are prefixed with $$ne, $gt, $in, $regex, $where — and any of them can be injected wherever the application passes a raw request body or query-string value into a find(), update(), or aggregate() call without casting it to the expected type. A request body of {"username": {"$gt": ""}} matches every username in the collection. A regex payload like {"$regex": "^admin"} can be used to brute-force field values character by character through timing differences, effectively exfiltrating password hashes or reset tokens one character at a time. The $where operator is the most dangerous variant because it executes arbitrary JavaScript inside the MongoDB server process, turning an injection bug into remote code execution if server-side JavaScript is enabled (security.javascriptEnabled, on by default before MongoDB 4.4 hardened the operator's use in sharded clusters).

Which Operators and Databases Are Most Commonly Exploited?

MongoDB's $where, $ne, $regex, and $gt/$lt operators are the most commonly exploited, because they are the easiest to trigger from ordinary HTTP parameters and the most likely to be passed through un-sanitized by frameworks like Express with body-parser or express.json(). Authentication bypass via $ne/$exists on password fields is the single most reported pattern in bug bounty reports tagged "NoSQL injection" on HackerOne, because Node.js/MongoDB stacks (the "MEAN"/"MERN" stack) parse incoming JSON bodies automatically, so an attacker only has to change a string field to a JSON object in the request body — no encoding required. CouchDB's Mango query selectors ($gt, $or) and its _find HTTP endpoint are exploited the same way when an application forwards query parameters directly. Redis is less commonly "injected" in the classic sense but is vulnerable to command injection when user input is concatenated into EVAL Lua scripts or redis-cli pipelines. Across all of these engines, the root cause is identical: the driver received a data structure instead of a scalar, and nothing validated the structure's shape before it reached the query engine.

What Real-World CVEs Demonstrate NoSQL Injection's Impact?

Two disclosed CVEs show NoSQL injection escalating from a query anomaly to full remote code execution in widely deployed MongoDB tooling. CVE-2019-10758 affected mongo-express, the popular web-based MongoDB admin UI, before version 0.54.0: a crafted request to the document-editing endpoint could inject a payload evaluated by the application's server-side JavaScript handling, giving an unauthenticated attacker code execution on the host running the admin interface — rated critical (CVSS 9.8) because mongo-express instances are frequently exposed to the internet with default credentials. CVE-2021-22911, disclosed in April 2021, hit Rocket.Chat versions before 3.9.4, 3.10.5, and 3.11.3: a NoSQL injection in a Meteor DDP method combined with a prototype-pollution flaw let an unauthenticated attacker achieve remote code execution on the Rocket.Chat server, also rated CVSS 9.8. Both cases followed the same pattern documented in the 2012 research — user-controlled objects reaching a query or evaluation context that trusted their shape — nearly a decade apart, in production software with active security teams behind it.

How Is NoSQL Injection Different From SQL Injection?

NoSQL injection differs from SQL injection because it exploits data structure and operator semantics rather than string concatenation, so the standard SQL defenses — parameterized queries and prepared statements — don't directly apply. SQL injection breaks out of a string literal using quotes, comments, or UNION statements against a fixed, typed schema. NoSQL injection instead sends a JSON object, array, or operator where the application expects a plain string or number, and the database happily evaluates it because most NoSQL engines are schema-less by design and accept whatever shape of document they're given. This means an application using an ODM like Mongoose can still be vulnerable if it calls .find(req.body) directly instead of mapping named, typed fields — Mongoose's schema casting helps but does not eliminate operator injection on fields typed as Mixed or on query filters built from unvalidated objects. It also means classic SQLi scanners and WAF signatures tuned for quotes and OR 1=1 frequently miss NoSQL payloads entirely, because there's no SQL syntax to fingerprint — the payload is valid JSON.

How Do You Detect and Prevent NoSQL Injection in Your Codebase?

You prevent NoSQL injection by strictly typing and validating every field before it reaches a query, rather than trusting the shape of incoming JSON. Concretely: reject any request field where an object or array arrives in place of an expected string or number (a single typeof value !== 'string' check on auth fields would have stopped the classic $ne bypass); use an allowlist of permitted query operators if your application must accept structured filters from clients, rather than a denylist; disable server-side JavaScript execution in MongoDB (--noscripting or security.javascriptEnabled: false) unless a specific feature requires $where or mapReduce; and use schema validation libraries — Joi, Zod, or Mongoose schemas with strict mode and no Mixed types on security-sensitive fields — at the API boundary, before data reaches the database driver. For detection, static analysis needs to flag every place a raw req.body, req.query, or req.params value flows into a MongoDB driver call (find, findOne, updateOne, aggregate) without an intervening type check or schema-cast step, and dynamic testing should include payloads like {"$ne": null}, {"$gt": ""}, and {"$regex": ".*"} against every JSON-accepting endpoint, not just ones with obvious search boxes.

How Safeguard Helps

Safeguard's reachability analysis traces whether a vulnerable code path — a raw object passed into a MongoDB, Mongoose, or CouchDB query call — is actually reachable from an untrusted HTTP input in your specific codebase, instead of flagging every dependency that merely contains a NoSQL driver. Griffin AI reviews the surrounding data flow to distinguish a genuinely exploitable operator-injection sink from a call site where input is already validated or cast, cutting the triage time security teams spend chasing NoSQL injection findings across large monorepos. Safeguard's SBOM generation and ingest track exact versions of mongo-express, Mongoose, and other MongoDB tooling across every repository and service, so a disclosure like CVE-2021-22911 can be matched against your fleet in minutes rather than days. When a fix is available — an upgraded driver version, added input-validation middleware, or a schema tightening change — Safeguard opens an auto-fix PR with the patch pre-applied so engineering teams can ship the remediation without doing the archaeology themselves.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.