Skip to content

[GHSA-ff7x-qrg7-qggm] dot-prop Prototype Pollution vulnerability#7461

Open
Wenxin-Jiang wants to merge 1 commit intoWenxin-Jiang/advisory-improvement-7461from
Wenxin-Jiang-GHSA-ff7x-qrg7-qggm
Open

[GHSA-ff7x-qrg7-qggm] dot-prop Prototype Pollution vulnerability#7461
Wenxin-Jiang wants to merge 1 commit intoWenxin-Jiang/advisory-improvement-7461from
Wenxin-Jiang-GHSA-ff7x-qrg7-qggm

Conversation

@Wenxin-Jiang
Copy link
Copy Markdown

Updates

  • Affected products

Comments
CVE-2020-8116 is a prototype-pollution vulnerability in dot-prop, but it is only reachable in versions that actually expose a write primitive. The vulnerable behavior lives in the library’s set() function, which walks a dot-delimited path and assigns into the target object at the final segment. The fix shipped in 4.2.1 and 5.1.1, where getPathSegments() was updated to reject __proto__, prototype, and constructor. Because set() (along with get(), has(), and delete()) consumes getPathSegments(), that denylist blocks the traversal pattern required for prototype pollution.

Versions 1.0.0 and 1.0.1 are not exploitable because they do not provide any write API at all. In those releases, the package consists entirely of a recursive getter:

// 1.0.0 index.js
module.exports = function getProp(obj, path) {
  if (!isObject(obj) || typeof path !== 'string') return obj;
  path = path.split('.');
  return getProp(obj[path.shift()], path.join('.'));
};

There is no set(), no delete(), no getPathSegments(), and no assignment sink anywhere in the exported API. Since the library exposes no mechanism to write into an object using attacker-controlled path segments, there is no way to reach Object.prototype pollution through the 1.x line. Any proof of concept aimed at 1.0.0 or 1.0.1 fails for a structural reason: there is simply no writable surface to call.

The first vulnerable release is 2.0.0, which introduced the split { get, set } API and, with it, the write-during-traversal pattern that makes prototype pollution possible:

// 2.0.0 index.js (abridged)
module.exports.set = function (obj, path, value) {
  var pathArr = path.split('.');
  pathArr.forEach(function (path, index) {
    if (!isObject(obj[path])) obj[path] = {};
    if (index === pathArr.length - 1) obj[path] = value;
    obj = obj[path];
  });
};

With an input such as __proto__.polluted, this code traverses through the inherited __proto__ accessor into Object.prototype, then performs the final assignment there. That is the exact prototype-pollution behavior later blocked by the denylist in 4.2.1 and 5.1.1.

Evidence

  • npm registry tarballs inspected: 1.0.0, 1.0.1, 2.0.0, 4.2.0, 4.2.1, 5.1.0, 5.1.1
  • 1.0.0 and 1.0.1 each export only a recursive getProp function and no write-capable API
  • 2.0.0 is the first release to add module.exports.set, which contains the vulnerable assign-during-walk logic
  • 4.2.1 and 5.1.1 add a denylist for __proto__, prototype, and constructor inside getPathSegments(), confirming that this traversal logic is the intended fix site
  • Non-exploitation in 1.0.0 and 1.0.1 is not a testing artifact; those versions are missing the required API surface entirely

Conclusion

The affected range for CVE-2020-8116 should begin at 2.0.0, not 1.0.0. Versions 1.0.0 and 1.0.1 are false positives because they do not contain the vulnerable set() implementation or any equivalent write sink.

@github-actions github-actions bot changed the base branch from main to Wenxin-Jiang/advisory-improvement-7461 April 20, 2026 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant