Introduction
A gap in Mongoose's query sanitization logic allowed the $nor operator to act as a free pass for injecting arbitrary NoSQL operators into MongoDB queries, completely bypassing the sanitizeFilter mechanism that developers rely on for protection. For any Node.js application that trusts sanitizeFilter to neutralize user controlled query input, this vulnerability (CVSS 7.5) opens a direct path to authentication bypass and unauthorized data access.
Mongoose is the dominant MongoDB Object Data Modeling library for Node.js, maintained by Automattic. With roughly 2.2 million weekly downloads on npm and over 27,400 GitHub stars, it is deeply embedded in the Node.js ecosystem and powers a significant portion of applications that interact with MongoDB. A sanitization bypass in Mongoose has an outsized blast radius given this adoption.
Technical Information
Root Cause: Missing $nor in Recursive Sanitization
Mongoose's sanitizeFilter() function, located in lib/helpers/query/sanitizeFilter.js, is designed to protect against NoSQL injection by iterating over every key in a query filter object. When it encounters a value containing dollar prefixed properties (detected by the internal hasDollarKeys() helper), it wraps that value in a $eq operator, effectively neutralizing any injected query operators.
For logical operators like $and and $or, which accept arrays of sub condition objects, the function needs to recurse into each element and sanitize it independently. The vulnerable code only checked for two of MongoDB's three logical array operators:
// BEFORE (vulnerable) if (key === '$and' || key === '$or') { sanitizeFilter(value); continue; }
MongoDB's $nor operator is structurally identical to $and and $or: it takes an array of condition objects. But because $nor was missing from this check, the function never recursed into its contents. And because the $nor value is an array, it does not trigger hasDollarKeys(), which only inspects plain objects for dollar prefixed keys. The result: any operators nested inside a $nor clause passed through to MongoDB completely untouched.
Attack Flow
An attacker exploiting this vulnerability would follow these steps:
-
Identify a vulnerable endpoint. The target application must use Mongoose with
sanitizeFilterenabled and pass user controlled input directly into a query method. A common vulnerable pattern isModel.findOne(req.body), where the entire HTTP request body becomes the MongoDB query filter. -
Craft a malicious payload. The attacker constructs a JSON payload that places malicious query operators inside a
$norarray. For example, operators like$ne(not equal),$gt(greater than), or$regexcan be nested within$norclauses. -
Submit the payload. The attacker sends the crafted JSON as the request body to the vulnerable endpoint. Because
sanitizeFilterdoes not recurse into$nor, the malicious operators reach MongoDB's query engine without being wrapped in$eq. -
Achieve unauthorized access. Depending on the application logic, this can result in authentication bypass (e.g., matching any user whose password is not equal to an empty string), unauthorized data enumeration, or data exfiltration.
The CVSS 3.1 vector confirms the severity profile: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N. The attack is network accessible, low complexity, requires no privileges or user interaction, and has high confidentiality impact.
Applications that explicitly map fields before querying (e.g., Model.findOne({ user: req.body.user, pwd: req.body.pwd })) or that validate input schemas and whitelist fields are not affected by this vulnerability.
Patch Information
The Mongoose maintainers addressed CVE-2026-42334 with commit b804e34, authored by Valeri Karpov on February 4, 2026, with the message "fix: handle other top-level query operators in sanitizeFilter." Patched versions were released across all supported major release lines: 6.13.9, 7.8.9, 8.22.1, and 9.1.6.
The core fix adds $nor to the set of recursively sanitized logical operators:
// AFTER (patched) if (key === '$and' || key === '$or' || key === '$nor') { sanitizeFilter(value); continue; }
The commit also went further with defense in depth hardening. Several other potentially dangerous top level operators that were previously unhandled now throw a MongooseError if encountered without being wrapped in the trusted() escape hatch:
} else if (key === '$jsonSchema' || key === '$where' || key === '$expr' || key === '$text') { throw new MongooseError(key + ' is not allowed with sanitizeFilter'); }
This is a meaningful addition: operators like $where (which accepts arbitrary JavaScript) and $expr (which allows aggregation expressions) could be abused for injection if an attacker controlled their values. The trusted() function in lib/helpers/query/trusted.js was also updated to accept function types alongside objects, which is necessary since $where can take a function value.
The accompanying test file (test/helpers/query.sanitizeFilter.test.js) was updated with 81 new lines of coverage, including a dedicated test case verifying that $nor clauses now have their nested dollar key operators wrapped in $eq, and separate test cases for each newly blocked operator ($jsonSchema, $where, $expr, $text) confirming they throw when untrusted and pass through when wrapped in trusted().
To apply the fix, upgrade the mongoose npm package to version ^6.13.9, ^7.8.9, ^8.22.1, or ^9.1.6 depending on the major version your application uses.
Affected Systems and Versions
The vulnerability affects all Mongoose versions across four major release lines that include the sanitizeFilter feature:
| Affected Version Range | Fixed Version |
|---|---|
| Versions prior to 6.13.9 | 6.13.9 |
| Versions 7.0.0 through 7.8.8 | 7.8.9 |
| Versions 8.0.0 through 8.22.0 | 8.22.1 |
| Versions 9.0.0 through 9.1.5 | 9.1.6 |
Only applications that explicitly enable sanitizeFilter and pass unsanitized user input directly into query methods are vulnerable. Applications that validate input schemas, whitelist fields, or explicitly map request properties to query parameters are not affected.
Vendor Security History
Mongoose has experienced query injection vulnerabilities in the past. Notably, CVE-2025-23061 was a critical severity (CVSS 9.0) search injection vulnerability related to the $where clause. The recurrence of injection flaws in the query sanitization layer suggests that this is a structurally challenging area of the codebase. The patch for CVE-2026-42334 reflects awareness of this pattern: beyond fixing the immediate $nor issue, the commit proactively blocks $where, $expr, $jsonSchema, and $text operators from passing through sanitizeFilter untrusted, which is a welcome defense in depth measure.



