CVE-2026-125117
Mongoose walks into inherited properties when hydrating, setting, and merging, allowing overwrites of built-in functions (denial of service) and shared schema state
Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment. Prior to 6.13.12, 7.8.13, 8.24.7, and 9.11.4, Mongoose can descend into inherited properties while loading database documents in init(), setting dotted paths in $__set, and merging update documents in utils.mergeClone. Attacker-controlled keys such as toString or valueOf can therefore cause Mongoose to write into shared built-in functions instead of an own property. A crafted document, Mixed path, non-strict document or subdocument, findOneAndReplace() replacement, chained update, or Query.prototype.merge() source can overwrite Object.prototype.toString.call, causing later queries on unrelated models to fail until the process restarts. Separately, when an attacker controls the dotted path passed to doc.set(path, value) for a subdocument configured with strict: false, descent through $__set can reach $__schema and alter shared validators or schema options for later documents. Mongoose already blocks proto, constructor, and prototype, so this issue overwrites properties on reachable shared objects rather than adding new properties directly to Object.prototype. This issue is fixed in versions 6.13.12, 7.8.13, 8.24.7, and 9.11.4.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- Low
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used 8.2
Mongoose walks into inherited properties when hydrating, setting, and merging, allowing overwrites of built-in functions (denial of service) and shared schema state
Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment. Prior to 6.13.12, 7.8.13, 8.24.7, and 9.11.4, Mongoose can descend into inherited properties while loading database documents in init(), setting dotted paths in $__set, and merging update documents in utils.mergeClone. Attacker-controlled keys such as toString or valueOf can therefore cause Mongoose to write into shared built-in functions instead of an own property. A crafted document, Mixed path, non-strict document or subdocument, findOneAndReplace() replacement, chained update, or Query.prototype.merge() source can overwrite Object.prototype.toString.call, causing later queries on unrelated models to fail until the process restarts. Separately, when an attacker controls the dotted path passed to doc.set(path, value) for a subdocument configured with strict: false, descent through $__set can reach $__schema and alter shared validators or schema options for later documents. Mongoose already blocks proto, constructor, and prototype, so this issue overwrites properties on reachable shared objects rather than adding new properties directly to Object.prototype. This issue is fixed in versions 6.13.12, 7.8.13, 8.24.7, and 9.11.4.
- Record
CVE-2026-125117- CVSS 3.1
- 8.2 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H - Weakness
- CWE-1321
- Updated
- 2026-11-10
EUVDEUVD-2026-120498 8.2
Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment. Prior to 6.13.12, 7.8.13, 8.24.7, and 9.11.4, Mongoose can descend into inherited properties while loading database documents in init(), setting dotted paths in $__set, and merging update documents in utils.mergeClone. Attacker-controlled keys such as toString or valueOf can therefore cause Mongoose to write into shared built-in functions instead of an own property. A crafted document, Mixed path, non-strict document or subdocument, findOneAndReplace() replacement, chained update, or Query.prototype.merge() source can overwrite Object.prototype.toString.call, causing later queries on unrelated models to fail until the process restarts. Separately, when an attacker controls the dotted path passed to doc.set(path, value) for a subdocument configured with strict: false, descent through $__set can reach $__schema and alter shared validators or schema options for later documents. Mongoose already blocks proto, constructor, and prototype, so this issue overwrites properties on reachable shared objects rather than adding new properties directly to Object.prototype. This issue is fixed in versions 6.13.12, 7.8.13, 8.24.7, and 9.11.4.
- Record
EUVD-2026-120498- CVSS 3.1
- 8.2 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H - Updated
- 2026-11-10
GitHub AdvisoriesGHSA-8332-j7wj-wjw4 8.2
Mongoose walks into inherited properties when hydrating, setting, and merging, allowing overwrites of built-in functions (denial of service) and shared schema state
Summary
Three Mongoose code paths copy data into objects by property name without checking whether the property is the object's own or inherited from its prototype:
- Loading a document from the database (
init(), also used byModel.hydrate()) - Setting a dotted path on a document (
$__set, used bynew Model(obj),doc.set()anddoc.$set()) - Merging update documents (
utils.mergeClone, used byfindOneAndReplace(), chained update calls andQuery.prototype.merge())
When a key names an inherited property, such as toString or valueOf, or a document internal such as $__schema, Mongoose writes into the shared object behind that property. The data comes from the attacker.
- Denial of service. For example,
{ "toString": { "call": 1 } }overwritesObject.prototype.toString.call. Mongoose and most other libraries rely onObject.prototype.toString.call(). After the overwrite, every later query in the process throwsTypeError: _toString.call is not a functionuntil the process restarts. This includes queries on unrelated models. - Changing shared schema state. Through a subdocument with
strict: false, a path such asprofile.$__schema.paths.email.validatorsreaches the subdocument's schema, which every document shares. Setting it to[]removes therequiredvalidator for every document in the process.
Mongoose already blocked __proto__, constructor and prototype, so these bugs cannot add properties to Object.prototype itself. They can still overwrite methods and properties of shared built-in functions and of Mongoose's internal objects.
Details
1. Loading documents: init()
if (!schemaType && utils.isPOJO(value)) {
// assume nested object
if (!doc[i]) { doc[i] = {}; ... }
init(self, value, doc[i], opts, path + '.');
}
For a stored field named toString, doc[i] is the inherited Object.prototype.toString. It is truthy, so init() recurses into that function and copies the stored subfields onto it.
This runs for every document Mongoose loads: find(), findOne(), cursors, populated documents and Model.hydrate(). It runs whatever the strict setting, and it applies to top-level and nested paths alike. lean() queries are not affected.
A malicious document can get into the collection in several ways:
- through a model with
strict: false, for examplenew Model(req.body).save(); - through another application or the raw MongoDB driver;
- through any update that writes arbitrary keys.
2. Setting dotted paths: $__set
When it walks a dotted path, $__set read obj[parts[i]] and descended into whatever it found. That included inherited functions, such as Object.prototype.toString on a plain object or Document.prototype.toObject on a subdocument. On subdocuments it also included non-function internals that are prototype getters, such as $__schema, schema, $__middleware and $__schemaTypeOptions. Those point at objects that every document of the model shares.
Attacker-controlled input reaches this path through:
- A
Mixedpath on a default, strict schema:new Model({ "mixed.toString.call": 1 }), ordoc.set({ "mixed.toString.call": 1 }). Nothing needs to be saved. - Any root path on a schema with
strict: false: for exampledoc.set('toString.call', 1). - A subdocument with
strict: false, when the application passes a user-controlled path todoc.set(path, value): for exampledoc.set('profile.$__schema.paths.email.validators', []).
3. Merging updates: utils.mergeClone
if (typeof to[key] === 'undefined') {
to[key] = clone(fromObj[key]);
} else if (isObject(val)) {
mergeClone(to[key], val); // to[key] may be an inherited built-in
}
to[key] was read without an own-property check, so a key such as toString recursed into Object.prototype.toString. This affects:
Model.findOneAndReplace(filter, replacement). It always merges the replacement into the query's…
- Record
GHSA-8332-j7wj-wjw4- CVSS 3.1
- 8.2 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H - Weakness
- CWE-1321
- Updated
- 2026-11-10
NVD 8.2
Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment. Prior to 6.13.12, 7.8.13, 8.24.7, and 9.11.4, Mongoose can descend into inherited properties while loading database documents in init(), setting dotted paths in $__set, and merging update documents in utils.mergeClone. Attacker-controlled keys such as toString or valueOf can therefore cause Mongoose to write into shared built-in functions instead of an own property. A crafted document, Mixed path, non-strict document or subdocument, findOneAndReplace() replacement, chained update, or Query.prototype.merge() source can overwrite Object.prototype.toString.call, causing later queries on unrelated models to fail until the process restarts. Separately, when an attacker controls the dotted path passed to doc.set(path, value) for a subdocument configured with strict: false, descent through $__set can reach $__schema and alter shared validators or schema options for later documents. Mongoose already blocks proto, constructor, and prototype, so this issue overwrites properties on reachable shared objects rather than adding new properties directly to Object.prototype. This issue is fixed in versions 6.13.12, 7.8.13, 8.24.7, and 9.11.4.
- Record
CVE-2026-125117- CVSS 3.1
- 8.2 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H - Weakness
- CWE-1321
- Updated
- 2026-11-10
OSV 8.2
Mongoose walks into inherited properties when hydrating, setting, and merging, allowing overwrites of built-in functions (denial of service) and shared schema state
Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment. Prior to 6.13.12, 7.8.13, 8.24.7, and 9.11.4, Mongoose can descend into inherited properties while loading database documents in init(), setting dotted paths in $__set, and merging update documents in utils.mergeClone. Attacker-controlled keys such as toString or valueOf can therefore cause Mongoose to write into shared built-in functions instead of an own property. A crafted document, Mixed path, non-strict document or subdocument, findOneAndReplace() replacement, chained update, or Query.prototype.merge() source can overwrite Object.prototype.toString.call, causing later queries on unrelated models to fail until the process restarts. Separately, when an attacker controls the dotted path passed to doc.set(path, value) for a subdocument configured with strict: false, descent through $__set can reach $__schema and alter shared validators or schema options for later documents. Mongoose already blocks proto, constructor, and prototype, so this issue overwrites properties on reachable shared objects rather than adding new properties directly to Object.prototype. This issue is fixed in versions 6.13.12, 7.8.13, 8.24.7, and 9.11.4.
- Record
CVE-2026-125117- CVSS 3.1
- 8.2 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H - Weakness
- CWE-1321
- Updated
- 2026-11-11
OSVGHSA-8332-j7wj-wjw4 8.2
Mongoose walks into inherited properties when hydrating, setting, and merging, allowing overwrites of built-in functions (denial of service) and shared schema state
Summary
Three Mongoose code paths copy data into objects by property name without checking whether the property is the object's own or inherited from its prototype:
- Loading a document from the database (
init(), also used byModel.hydrate()) - Setting a dotted path on a document (
$__set, used bynew Model(obj),doc.set()anddoc.$set()) - Merging update documents (
utils.mergeClone, used byfindOneAndReplace(), chained update calls andQuery.prototype.merge())
When a key names an inherited property, such as toString or valueOf, or a document internal such as $__schema, Mongoose writes into the shared object behind that property. The data comes from the attacker.
- Denial of service. For example,
{ "toString": { "call": 1 } }overwritesObject.prototype.toString.call. Mongoose and most other libraries rely onObject.prototype.toString.call(). After the overwrite, every later query in the process throwsTypeError: _toString.call is not a functionuntil the process restarts. This includes queries on unrelated models. - Changing shared schema state. Through a subdocument with
strict: false, a path such asprofile.$__schema.paths.email.validatorsreaches the subdocument's schema, which every document shares. Setting it to[]removes therequiredvalidator for every document in the process.
Mongoose already blocked __proto__, constructor and prototype, so these bugs cannot add properties to Object.prototype itself. They can still overwrite methods and properties of shared built-in functions and of Mongoose's internal objects.
Details
1. Loading documents: init()
if (!schemaType && utils.isPOJO(value)) {
// assume nested object
if (!doc[i]) { doc[i] = {}; ... }
init(self, value, doc[i], opts, path + '.');
}
For a stored field named toString, doc[i] is the inherited Object.prototype.toString. It is truthy, so init() recurses into that function and copies the stored subfields onto it.
This runs for every document Mongoose loads: find(), findOne(), cursors, populated documents and Model.hydrate(). It runs whatever the strict setting, and it applies to top-level and nested paths alike. lean() queries are not affected.
A malicious document can get into the collection in several ways:
- through a model with
strict: false, for examplenew Model(req.body).save(); - through another application or the raw MongoDB driver;
- through any update that writes arbitrary keys.
2. Setting dotted paths: $__set
When it walks a dotted path, $__set read obj[parts[i]] and descended into whatever it found. That included inherited functions, such as Object.prototype.toString on a plain object or Document.prototype.toObject on a subdocument. On subdocuments it also included non-function internals that are prototype getters, such as $__schema, schema, $__middleware and $__schemaTypeOptions. Those point at objects that every document of the model shares.
Attacker-controlled input reaches this path through:
- A
Mixedpath on a default, strict schema:new Model({ "mixed.toString.call": 1 }), ordoc.set({ "mixed.toString.call": 1 }). Nothing needs to be saved. - Any root path on a schema with
strict: false: for exampledoc.set('toString.call', 1). - A subdocument with
strict: false, when the application passes a user-controlled path todoc.set(path, value): for exampledoc.set('profile.$__schema.paths.email.validators', []).
3. Merging updates: utils.mergeClone
if (typeof to[key] === 'undefined') {
to[key] = clone(fromObj[key]);
} else if (isObject(val)) {
mergeClone(to[key], val); // to[key] may be an inherited built-in
}
to[key] was read without an own-property check, so a key such as toString recursed into Object.prototype.toString. This affects:
Model.findOneAndReplace(filter, replacement). It always merges the replacement into the query's…
- Record
GHSA-8332-j7wj-wjw4- CVSS 3.1
- 8.2 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:H - Weakness
- CWE-1321
- Updated
- 2026-11-10
Affected products
Affected packages
History
| Recorded | Changed | Sources |
|---|---|---|
| published | EUVD | |
| published | EUVD | |
| affected, references | OSV | |
| affected, facts, references | GitHub Advisories, NVD | |
| references | CVE List | |
| aliases, references | NVD, OSV | |
| cwes, references, severity, title | CVE List | |
| first indexed | EUVD |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-125117 is a high vulnerability (CVSS 8.2) in Automattic Mongoose, published November 9, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.58%, the 48th percentile. Fixed in mongoose 6.13.12.
References
github.com/Automattic/mongoose/security/advisories/GHSA-8332-j7wj-wjw4
github.com/Automattic/mongoose/commit/18b5513dd463731a2caf0d3395ef1d9eb0735f50
github.com/Automattic/mongoose/commit/2a195d19a4dd240f039a0a226614d5804e8187ee
github.com/Automattic/mongoose/commit/3cb702b8d079c3e267f0b10f41673a1590f703c8
github.com/Automattic/mongoose/commit/85cf897105edfeb5f56be42a18a68704434cac82
github.com/Automattic/mongoose/commit/8cee51beead554df1f3d05645edb439c69eb2a9b
Show 9 moreShow less
github.com/Automattic/mongoose/commit/8eb74cb4a550cbe0225963b07aebacbd999d4b74
github.com/Automattic/mongoose/releases/tag/6.13.12
github.com/Automattic/mongoose/releases/tag/7.8.13
github.com/Automattic/mongoose/releases/tag/8.24.7
github.com/Automattic/mongoose/releases/tag/9.11.4
nvd.nist.gov/vuln/detail/CVE-2026-125117
github.com/advisories/GHSA-8332-j7wj-wjw4
github.com/CVEProject/cvelistV5/tree/main/cves/2026/125xxx/CVE-2026-125117.json
github.com/Automattic/mongoose
Left out here: the rest of 2 source descriptions. The JSON record has them.