js-yaml has prototype pollution in merge (<<)
Description
js-yaml is a JavaScript YAML parser and dumper. In js-yaml before 4.1.1 and 3.14.2, it's possible for an attacker to modify the prototype of the result of a parsed yaml document via prototype pollution (__proto__). All users who parse untrusted yaml documents may be impacted. The problem is patched in js-yaml 4.1.1 and 3.14.2. Users can protect against this kind of attack on the server by using node --disable-proto=delete or deno (in Deno, pollution protection is on by default).
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
js-yaml before 4.1.1 and 3.14.2 allows prototype pollution via the YAML merge (<<) operator, enabling attackers to modify object prototypes.
Vulnerability
Overview
CVE-2025-64718 is a prototype pollution vulnerability in js-yaml, a popular JavaScript YAML parser and dumper. The flaw exists in versions before 4.1.1 and 3.14.2, specifically in how the YAML merge operator (<<) handles keys during mapping. When parsing untrusted YAML documents, an attacker can inject a key named __proto__ to pollute the prototype of the resulting object, thereby modifying default properties across the application [1][3].
Exploitation
The exploit is triggered by crafting a YAML document that uses the merge operator to set properties on __proto__. No authentication or special privileges are required beyond the ability to submit a YAML document to the parser. Any application using js-yaml to parse untrusted input—such as configuration files, API payloads, or user uploads—is vulnerable. The attack vector is local or remote depending on how the parser is integrated, but the prerequisite is always that the attacker can supply YAML content [2][4].
Impact
Successful prototype pollution can lead to a wide range of security impacts, including denial of service, property injection, and potentially arbitrary code execution if the polluted properties affect security-critical logic. In Node.js environments, this could bypass runtime protections or alter the behavior of dependencies that rely on object prototype checks [2][4].
Mitigation
The issue is patched in js-yaml version 4.1.1 and 3.14.2 [3][4]. Users are strongly advised to update immediately. As a server-side workaround, running Node.js with the --disable-proto=delete flag can mitigate the pollution vector, though this is not a complete fix. Deno users are protected by default due to built-in prototype pollution protections [1][2].
AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
js-yamlnpm | >= 4.0.0, < 4.1.1 | 4.1.1 |
js-yamlnpm | < 3.14.2 | 3.14.2 |
Affected products
1Patches
25278870a1745fix prototype pollution in merge (<<) (#731)
2 files changed · +41 −2
lib/js-yaml/loader.js+18 −2 modified@@ -121,6 +121,22 @@ function charFromCodepoint(c) { ); } +// set a property of a literal object, while protecting against prototype pollution, +// see https://github.com/nodeca/js-yaml/issues/164 for more details +function setProperty(object, key, value) { + // used for this specific key only because Object.defineProperty is slow + if (key === '__proto__') { + Object.defineProperty(object, key, { + configurable: true, + enumerable: true, + writable: true, + value: value + }); + } else { + object[key] = value; + } +} + var simpleEscapeCheck = new Array(256); // integer, for fast access var simpleEscapeMap = new Array(256); for (var i = 0; i < 256; i++) { @@ -278,7 +294,7 @@ function mergeMappings(state, destination, source, overridableKeys) { key = sourceKeys[index]; if (!_hasOwnProperty.call(destination, key)) { - destination[key] = source[key]; + setProperty(destination, key, source[key]); overridableKeys[key] = true; } } @@ -334,7 +350,7 @@ function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valu state.position = startPos || state.position; throwError(state, 'duplicated mapping key'); } - _result[keyNode] = valueNode; + setProperty(_result, keyNode, valueNode); delete overridableKeys[keyNode]; }
test/issues/0164.js+23 −0 added@@ -0,0 +1,23 @@ +'use strict'; + + +var assert = require('assert'); +var yaml = require('../../'); + + +test('should define __proto__ as a value (not invoke setter)', function () { + var object = yaml.load('{ __proto__: {polluted: bar} }'); + + assert.strictEqual(({}).hasOwnProperty.call(yaml.load('{}'), '__proto__'), false); + assert.strictEqual(({}).hasOwnProperty.call(object, '__proto__'), true); + assert(!object.polluted); +}); + + +test('should merge __proto__ as a value with << operator', function () { + var object = yaml.load('\npayload: &ref\n polluted: bar\n\nfoo:\n <<:\n __proto__: *ref\n '); + + assert.strictEqual(({}).hasOwnProperty.call(yaml.load('{}'), '__proto__'), false); + assert.strictEqual(({}).hasOwnProperty.call(object.foo, '__proto__'), true); + assert(!object.foo.polluted); +});
383665ff4248fix prototype pollution in merge (<<)
3 files changed · +41 −14
CHANGELOG.md+5 −0 modified@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.1.1] - 2025-11-12 +### Security +- Fix prototype pollution issue in yaml merge (<<) operator. + + ## [4.1.0] - 2021-04-15 ### Added - Types are now exported as `yaml.types.XXX`.
lib/loader.js+18 −12 modified@@ -120,6 +120,22 @@ function charFromCodepoint(c) { ); } +// set a property of a literal object, while protecting against prototype pollution, +// see https://github.com/nodeca/js-yaml/issues/164 for more details +function setProperty(object, key, value) { + // used for this specific key only because Object.defineProperty is slow + if (key === '__proto__') { + Object.defineProperty(object, key, { + configurable: true, + enumerable: true, + writable: true, + value, + }); + } else { + object[key] = value; + } +} + var simpleEscapeCheck = new Array(256); // integer, for fast access var simpleEscapeMap = new Array(256); for (var i = 0; i < 256; i++) { @@ -298,7 +314,7 @@ function mergeMappings(state, destination, source, overridableKeys) { key = sourceKeys[index]; if (!_hasOwnProperty.call(destination, key)) { - destination[key] = source[key]; + setProperty(destination, key, source[key]); overridableKeys[key] = true; } } @@ -358,17 +374,7 @@ function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valu throwError(state, 'duplicated mapping key'); } - // used for this specific key only because Object.defineProperty is slow - if (keyNode === '__proto__') { - Object.defineProperty(_result, keyNode, { - configurable: true, - enumerable: true, - writable: true, - value: valueNode - }); - } else { - _result[keyNode] = valueNode; - } + setProperty(_result, keyNode, valueNode); delete overridableKeys[keyNode]; }
test/issues/0164.js+18 −2 modified@@ -6,9 +6,25 @@ const yaml = require('../../'); it('should define __proto__ as a value (not invoke setter)', function () { - let object = yaml.load('{ __proto__: {foo: bar} }'); + let object = yaml.load('{ __proto__: {polluted: bar} }'); assert.strictEqual(({}).hasOwnProperty.call(yaml.load('{}'), '__proto__'), false); assert.strictEqual(({}).hasOwnProperty.call(object, '__proto__'), true); - assert(!object.foo); + assert(!object.polluted); +}); + + +it('should merge __proto__ as a value with << operator', function () { + let object = yaml.load(` +payload: &ref + polluted: bar + +foo: + <<: + __proto__: *ref + `); + + assert.strictEqual(({}).hasOwnProperty.call(yaml.load('{}'), '__proto__'), false); + assert.strictEqual(({}).hasOwnProperty.call(object.foo, '__proto__'), true); + assert(!object.foo.polluted); });
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-mh29-5h37-fv8mghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-64718ghsaADVISORY
- github.com/nodeca/js-yaml/commit/383665ff4248ec2192d1274e934462bb30426879ghsax_refsource_MISCWEB
- github.com/nodeca/js-yaml/commit/5278870a17454fe8621dbd8c445c412529525266ghsax_refsource_MISCWEB
- github.com/nodeca/js-yaml/issues/730ghsax_refsource_MISCWEB
- github.com/nodeca/js-yaml/security/advisories/GHSA-mh29-5h37-fv8mghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.