Apr 6, 2026·5 min read·22 visits
A flaw in defu < 6.1.5 allows prototype pollution via Object.assign() when merging unsanitized user input containing __proto__ keys, enabling attackers to alter default application properties.
The `defu` library, a popular utility for recursively assigning default properties, contains a prototype pollution vulnerability prior to version 6.1.5. Applications passing unsanitized user input as the primary argument to the `defu()` function permit attackers to override object properties via crafted JSON payloads, leading to configuration injection or potential application logic bypass.
The defu library provides recursive object merging functionality for JavaScript and Node.js applications. Prior to version 6.1.5, the library suffered from a prototype pollution vulnerability. The flaw exists in the internal cloning mechanism used to process default configurations.
The vulnerability, classified as CWE-1321 (Improperly Controlled Modification of Object Prototype Attributes), requires specific conditions to trigger. The target application must accept unsanitized user input, typically derived from parsed JSON payloads or untrusted database records, and pass it directly as the first argument to the defu() function.
Exploitation allows attackers to manipulate the prototype chain of objects within the Node.js or browser environment. By overriding default configurations, attackers can manipulate downstream logic. This often leads to property injection, authorization bypass, or in specific configurations, remote code execution primitives.
The root cause of the vulnerability resides in the _defu internal function responsible for preparing objects for the recursive merge. The library utilized the Object.assign({}, defaults) construct to clone the defaults object prior to initiating the merging logic.
In the ECMAScript specification, Object.assign employs the [[Set]] internal method for property assignment. When the source object contains a key explicitly named __proto__, the runtime invokes the setter for Object.prototype.__proto__ on the target object. Because the target is an empty object literal {} that inherits from Object.prototype, this action successfully modifies the prototype of the new object to match the attacker-supplied value.
The defu library implemented an explicit guard inside its recursive for...in loop to skip __proto__ and constructor keys. The flaw bypassed this defense because the vulnerable Object.assign call occurred during the initial cloning phase, before the loop executed. The cloned object inherited the malicious prototype properties prematurely.
The patch applied in version 6.1.5 rectifies the prototype setter invocation by modifying how the initial object clone is instantiated. The maintainers replaced the Object.assign({}, defaults) call with the ECMAScript object spread operator { ...defaults }.
The spread operator utilizes the [[DefineOwnProperty]] internal method rather than [[Set]]. When [[DefineOwnProperty]] processes a __proto__ key, it creates the key as a literal data property on the target object instead of resolving and executing the prototype setter. This prevents the prototype chain from being altered.
Additionally, the patch alters the iteration strategy. The for...in loop, which traverses both own and inherited enumerable properties, was replaced with Object.keys(). This enforces iteration exclusively over the object's own enumerable properties, ensuring that any properties inherited from a polluted global prototype are ignored during the merge phase.
// Relevant changes from commit 3942bfbbcaa72084bd4284846c83bd61ed7c8b29
- const object = Object.assign({}, defaults);
+ const object = { ...defaults };
- for (const key in baseObject) {
+ for (const key of Object.keys(baseObject as Record<string, any>)) {
if (key === "__proto__" || key === "constructor") {
continue;
}Exploiting this vulnerability requires the attacker to supply a crafted JSON payload containing a __proto__ key to an endpoint that passes the resulting parsed object to defu. Standard JSON parsing (JSON.parse) without a custom reviver function will instantiate an object containing a literal __proto__ property.
When the vulnerable application passes this parsed object to defu(userInput, { isAdmin: false }), the Object.assign({}, defaults) routine triggers. The runtime executes the setter, pointing the target object's internal [[Prototype]] to the attacker's supplied object structure.
Properties defined within the attacker's __proto__ object manifest on the resulting configuration object. This directly overrides the intended default values provided by the developer. The proof-of-concept below demonstrates the structural manipulation required to achieve property injection.
import { defu } from 'defu'
// Attacker-controlled input (e.g., from a parsed JSON request body)
const userInput = JSON.parse('{"__proto__":{"isAdmin":true}}')
// Vulnerable call: passing untrusted input as the first argument
const config = defu(userInput, { isAdmin: false })
console.log(config.isAdmin)
// Result: true — The attacker has successfully overridden the server's default configurationThe impact of prototype pollution depends heavily on the specific implementation details of the host application. The vulnerability carries a CVSS 3.1 score of 7.5 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N), indicating a severe impact on system integrity with no authentication required.
The immediate consequence is property injection. Attackers control the keys and values merged into configuration objects, creating an opportunity to bypass business logic. Modifying boolean flags, such as administrative access checks or feature toggles, is a common objective.
In environments using vulnerable template engines or executing system commands, prototype pollution escalates to Remote Code Execution (RCE). If the polluted properties flow into execution sinks (e.g., child_process functions reading from an environment object), attackers can achieve arbitrary command execution on the host system.
The definitive remediation is to upgrade the defu dependency to version 6.1.5 or later. This addresses the vulnerability at the source by utilizing safe cloning mechanisms and restricted property iteration.
Developers must implement strict input validation for all user-supplied data prior to processing. Utilizing robust schema validation libraries, such as Zod or Joi, ensures that dangerous internal keys like __proto__, constructor, and prototype are stripped before data reaches object merging utilities.
In high-security execution environments, administrators should consider locking down the prototype chain globally. Invoking Object.freeze(Object.prototype) prevents unauthorized modifications to the global object prototype, acting as an effective defense-in-depth measure against broad classes of prototype pollution vulnerabilities.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
defu unjs | < 6.1.5 | 6.1.5 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-1321 |
| CVSS Score | 7.5 |
| Attack Vector | Network |
| Impact | High Integrity |
| Exploit Status | Proof of Concept |
| KEV Status | Not Listed |
The product receives input from an upstream component that specifies attributes that are to be initialized or updated in an object, but it does not properly control modifications of attributes of the object prototype.
Adobe ColdFusion versions 2025.9 and 2023.20 and earlier are affected by an Unrestricted Upload of File with Dangerous Type vulnerability (CWE-434). An unauthenticated remote attacker can exploit this flaw to upload malicious ColdFusion Markup Language (CFML) files directly into web-accessible directories. Accessing the uploaded script triggers arbitrary code execution in the security context of the running service account.
CVE-2026-46599 (also identified by Go vulnerability alias GO-2026-5032) is a high-severity denial-of-service vulnerability in the Go image repository, specifically within the TIFF decoder's PackBits decompression engine. A lack of resource limits during the parsing of Run-Length Encoded PackBits streams allows an attacker to construct a crafted TIFF image that achieves significant decompression amplification. This flaw enables an unauthenticated remote attacker to exhaust system resources, leading to an Out-of-Memory crash or a prolonged application hang.
A property shadowing vulnerability exists in protobufjs where schema-derived names can collide with and overwrite runtime-critical internal helper properties. This issue leads to uncaught runtime exceptions and crash-based Denial of Service.
An integer truncation vulnerability (CWE-197) exists in SQLite before version 3.50.2 during the processing of aggregate queries with more than 32,767 distinct column references. This causes an internal 32-bit counter to truncate to a signed 16-bit integer, producing negative values that cause out-of-bounds heap operations in release builds.
An integer overflow vulnerability in the Windows kernel-mode HTTP driver (HTTP.sys) allows an unauthenticated remote attacker to execute arbitrary code with kernel privileges or cause a Denial of Service via a specially crafted sequence of HTTP request headers.
A memory corruption vulnerability exists in the FTS5 (Full-Text Search 5) extension of SQLite prior to version 3.53.2. An attacker can construct a malicious database file containing corrupt FTS5 page data. Querying this database triggers out-of-bounds reads and heap-based buffer overflows, potentially causing a crash or arbitrary code execution.