The vulnerable pattern is deceptively simple: MyModel.updateOne(filter, req.body). This exact code appears in tutorials, Stack Overflow answers, and production APIs worldwide because it's the intuitive way to write an update endpoint. The CVE exposes that this pattern silently enables prototype pollution through __proto__ injection in the body—and the casting layer masks its own damage.
When Mongoose processes an update document, it performs deep schema introspection on every property. If you pass __proto__ in the update payload, the casting logic treats inherited properties as schema types, sets $fullPath and $parentSchemaDocArray directly onto Object.prototype, then throws an exception. The throw is the camouflage: developers see a casting error, assume they passed invalid input, and move on. Meanwhile, those two properties—Mongoose's internal schema traversal state—persist on Object.prototype for the entire process lifetime. Every subsequent document instantiation inherits this contaminated state.
This isn't classic prototype pollution where an attacker sets arbitrary flags like isAdmin. The injected properties are semantically meaningful to Mongoose's schema resolution machinery. An attacker who achieves injection isn't just toggling a boolean—they're injecting what looks like legitimate Mongoose internals, which could interfere with schema resolution in subsequent requests or confuse tooling that inspects Object.prototype. The threat model extends beyond the immediate request.
The affected versions are 6.13.10, 7.8.10, 8.24.1, and 9.7.2 forward. The EPSS score (0.00369) reflects low immediate exploitation probability, but this misreads the risk. The real exposure is in dependency trees: thousands of codebases use the req.body passthrough pattern without understanding the prototype pollution vector, and many won't update. Additionally, Mongoose has a history of narrow casting-layer fixes for similar issues—each technically correct for its vector but leaving the underlying traversal logic untouched. Expect follow-on CVEs for related properties.
For defenders: validate update inputs at the API boundary before passing them to Mongoose. Do not pass raw req.body to updateOne, updateMany, or findOneAndUpdate. A schema validation layer that explicitly blocks __proto__, constructor, and prototype properties before they reach the ODM is the robust solution—don't rely on Mongoose's casting layer to protect you.