CVE-2018-3721
Description
lodash node module before 4.17.5 suffers from a Modification of Assumed-Immutable Data (MAID) vulnerability via defaultsDeep, merge, and mergeWith functions, which allows a malicious user to modify the prototype of "Object" via __proto__, causing the addition or modification of an existing property that will exist on all objects.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Lodash before 4.17.5 allows prototype pollution via defaultsDeep, merge, and mergeWith functions, enabling modification of Object.prototype.
Vulnerability
Lodash versions prior to 4.17.5 contain a prototype pollution vulnerability in the defaultsDeep, merge, and mergeWith functions. The bug allows a malicious user to modify the prototype of Object via the __proto__ key, causing the addition or modification of an existing property that will exist on all objects. The affected functions do not properly guard against merging properties onto __proto__ objects [1][2][3].
Exploitation
An attacker can exploit this vulnerability by providing a crafted object with a __proto__ key to any application that uses the vulnerable lodash functions on user-supplied data. No authentication or special network position is required if the application processes untrusted input through these functions. The attacker simply needs to include a property like "__proto__": { "polluted": true } in the input object [1][2].
Impact
Successful exploitation allows the attacker to add or modify properties on the global Object.prototype. This can lead to unexpected behavior across the application, including denial of service, property injection, and in some cases privilege escalation if the polluted property affects security-sensitive logic. The impact is widespread because the polluted property becomes available on all JavaScript objects [1][2].
Mitigation
The vulnerability is fixed in lodash version 4.17.5, released on 2018-01-12. Users should upgrade to 4.17.5 or later. The fix introduces a safeGet helper that returns undefined for the __proto__ key, preventing prototype pollution during merge operations [3]. No workaround is available for earlier versions; upgrading is the only complete mitigation.
AI Insight generated on May 22, 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 |
|---|---|---|
lodashnpm | < 4.17.5 | 4.17.5 |
lodash-railsRubyGems | < 4.17.5 | 4.17.5 |
Affected products
3- ghsa-coords2 versions
< 4.17.5+ 1 more
- (no CPE)range: < 4.17.5
- (no CPE)range: < 4.17.5
- HackerOne/lodash node modulev5Range: Versions before 4.17.5
Patches
1d8e069cc3410Avoid merging properties on to __proto__ objects.
2 files changed · +32 −3
lodash.js+17 −3 modified@@ -1245,6 +1245,20 @@ return result; } + /** + * Gets the value at `key`, unless `key` is "__proto__". + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ + function safeGet(object, key) { + return key == '__proto__' + ? undefined + : object[key]; + } + /** * Converts `set` to an array of its values. * @@ -3615,7 +3629,7 @@ } else { var newValue = customizer - ? customizer(object[key], srcValue, (key + ''), object, source, stack) + ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack) : undefined; if (newValue === undefined) { @@ -3642,8 +3656,8 @@ * counterparts. */ function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { - var objValue = object[key], - srcValue = source[key], + var objValue = safeGet(object, key), + srcValue = safeGet(source, key), stacked = stack.get(srcValue); if (stacked) {
test/test.js+15 −0 modified@@ -7539,6 +7539,21 @@ actual = _.groupBy([{ 'a': '__proto__' }], 'a'); assert.notOk(actual instanceof Array); }); + + QUnit.test('should not merge "__proto__" properties', function(assert) { + assert.expect(1); + + if (JSON) { + _.merge({}, JSON.parse('{"__proto__":{"a":1}}')); + + var actual = "a" in objectProto; + delete objectProto.a; + + assert.notOk(actual); + } else { + skipAssert(assert); + } + }); }()); /*--------------------------------------------------------------------------*/
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-fvqr-27wr-82fmghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2018-3721ghsaADVISORY
- github.com/lodash/lodash/commit/d8e069cc3410082e44eb18fcf8e7f3d08ebe1d4aghsax_refsource_MISCWEB
- github.com/rubysec/ruby-advisory-db/blob/master/gems/lodash-rails/CVE-2018-3721.ymlghsaWEB
- hackerone.com/reports/310443ghsax_refsource_MISCWEB
- security.netapp.com/advisory/ntap-20190919-0004ghsaWEB
- security.netapp.com/advisory/ntap-20190919-0004/mitrex_refsource_CONFIRM
News mentions
0No linked articles in our index yet.