Applications that pass unsanitized user input (e.g. parsed JSON request bodies, database records, or config files from untrusted sources) as the first argument to defu() are vulnerable to prototype pollution.
A crafted payload containing a __proto__ key can override intended default values in the merged result:
import { defu } from 'defu'
const userInput = JSON.parse('{"__proto__":{"isAdmin":true}}')
const config = defu(userInput, { isAdmin: false })
config.isAdmin // true — attacker overrides the server default
The internal _defu function used Object.assign({}, defaults) to copy the defaults object. Object.assign invokes the __proto__ setter, which replaces the resulting object's [[Prototype]] with attacker-controlled values. Properties inherited from the polluted prototype then bypass the existing __proto__ key guard in the for...in loop and land in the final result.
Replace Object.assign({}, defaults) with object spread ({ ...defaults }), which uses [[DefineOwnProperty]] and does not invoke the __proto__ setter.
<= 6.1.4
Reported by @BlackHatExploitation
{
"cwe_ids": [
"CWE-1321"
],
"severity": "HIGH",
"nvd_published_at": null,
"github_reviewed": true,
"github_reviewed_at": "2026-04-04T06:17:53Z"
}