---
id: "CVE-2026-125118"
page: "https://infrastack.ai/live/CVE-2026-125118"
kind: "vulnerability"
aliases: ["CVE-2026-125118", "GHSA-6972-9mcm-vhwj"]
title: "Mongoose: Prototype pollution via Schema.prototype.virtual()"
severity: "medium"
cvss: 6.5
epss: null
exploited: false
status: "open"
category: "package"
products: [{"name": "mongoose", "fixed": ["6.13.12"], "affected": "< 6.13.12", "ecosystem": "npm"}, {"name": "mongoose", "fixed": ["7.8.13"], "affected": ">= 7.0.0, < 7.8.13", "ecosystem": "npm"}, {"name": "mongoose", "fixed": ["8.24.7"], "affected": ">= 8.0.0, < 8.24.7", "ecosystem": "npm"}, {"name": "mongoose", "fixed": ["9.11.4"], "affected": ">= 9.0.0, < 9.11.4", "ecosystem": "npm"}]
ecosystems: ["npm"]
tags: ["cwe-1321", "javascript", "mongoose", "node.js", "nodejs", "package"]
not_affected_if: ["no-user-controlled-field-names", "static-schemas"]
published_at: "2026-11-09T23:17:22+00:00"
first_seen_at: "2026-11-10T20:46:44+00:00"
updated_at: "2026-11-10T21:15:58+00:00"
sources: [{"source": "ghsa", "url": "https://github.com/advisories/GHSA-6972-9mcm-vhwj", "first_seen_at": "2026-11-10T20:46:44+00:00"}, {"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-125118", "first_seen_at": "2026-11-10T21:15:58+00:00"}]
exploit_sources: []
---

# Mongoose: Prototype pollution via Schema.prototype.virtual()

Link for people: https://infrastack.ai/live/CVE-2026-125118 (this .md is for agents)

Mongoose's Schema.virtual() does not block __proto__, constructor or prototype path segments, so a crafted virtual name writes onto Object.prototype and Function.prototype. An attacker who controls schema field names can make every object appear to have extra properties, such as a spoofed isAdmin flag.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- npm:mongoose affected < 6.13.12 fixed 6.13.12
- npm:mongoose affected >= 7.0.0, < 7.8.13 fixed 7.8.13
- npm:mongoose affected >= 8.0.0, < 8.24.7 fixed 8.24.7
- npm:mongoose affected >= 9.0.0, < 9.11.4 fixed 9.11.4

## How to check

- Check the installed Mongoose version with `npm ls mongoose`.
- Look for code that builds schema virtuals or field names from user-controlled or dynamic input, such as CMS form builders or schema-as-code.

## Fix

- `6.13.12` on the 6.x line
- `7.8.13` on the 7.x line
- `8.24.7` on the 8.x line
- `9.11.4` on the 9.x line

## Timeline

- 2026-11-10T20:46:44+00:00 ghsa https://github.com/advisories/GHSA-6972-9mcm-vhwj
- 2026-11-10T21:15:58+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-125118

## Documents

- [advisory] Maintainer's advisory: api.github.com https://api.github.com/repos/Automattic/mongoose/security-advisories/GHSA-6972-9mcm-vhwj
- [advisory] Maintainer's advisory: github.com https://github.com/Automattic/mongoose/security/advisories/GHSA-6972-9mcm-vhwj
- [fix] Patch: github.com https://github.com/Automattic/mongoose/commit/318f7e09dd363a1dfddb8180878488dccd2796d1
- [fix] Patch: github.com https://github.com/Automattic/mongoose/commit/74df7769b5a8d89c4413b764029911ee915ea467
- [fix] Patch: github.com https://github.com/Automattic/mongoose/commit/7a2a6567abbb72c0430c8cc5b7942141844fecff
- [fix] Patch: github.com https://github.com/Automattic/mongoose/commit/fb467e6d33174293dc0360649f20ce68d99117a9
- [fix] Release: github.com https://github.com/Automattic/mongoose/releases/tag/6.13.12
- [fix] Release: github.com https://github.com/Automattic/mongoose/releases/tag/7.8.13
- [fix] Release: github.com https://github.com/Automattic/mongoose/releases/tag/8.24.7
- [fix] Release: github.com https://github.com/Automattic/mongoose/releases/tag/9.11.4

## From the sources

### 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:

```javascript
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

```javascript
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).

---

_Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai_
