diff --git a/advisories/github-reviewed/2026/07/GHSA-28xv-ph75-77wh/GHSA-28xv-ph75-77wh.json b/advisories/github-reviewed/2026/07/GHSA-28xv-ph75-77wh/GHSA-28xv-ph75-77wh.json index c43dcded9650..29e09149ec8f 100644 --- a/advisories/github-reviewed/2026/07/GHSA-28xv-ph75-77wh/GHSA-28xv-ph75-77wh.json +++ b/advisories/github-reviewed/2026/07/GHSA-28xv-ph75-77wh/GHSA-28xv-ph75-77wh.json @@ -1,13 +1,13 @@ { "schema_version": "1.4.0", "id": "GHSA-28xv-ph75-77wh", - "modified": "2026-07-14T19:40:05Z", + "modified": "2026-08-16T15:54:32Z", "published": "2026-07-14T19:40:05Z", "aliases": [ "CVE-2026-54335" ], "summary": "Prototype pollution in @feathersjs/commons _.merge via JSON-parsed __proto__", - "details": "### Impact\n\nThe `_.merge(target, source)` utility exported by `@feathersjs/commons` recursively merges `source` into `target` by iterating `Object.keys(source)`. When `source` was produced by `JSON.parse` and contains a `__proto__` (or `constructor` / `prototype`) key, that key is returned as an own-enumerable property. The recursive merge then resolves `target['__proto__']` to `Object.prototype` and writes the attacker-supplied properties onto it, polluting the prototype for all plain objects in the process for the lifetime of the Node process.\n\n**Scope of real-world risk is limited.** No first-party Feathers package routes input — trusted or untrusted — through `commons._.merge`. The `@feathersjs/authentication` package, which does merge request-influenced data, uses `lodash/merge` (prototype-pollution-safe since 4.17.12), not this utility. Exploitation therefore requires a downstream plugin or application to pass JSON-parsed, attacker-controlled input directly through the exported `_.merge`.\n\n### Patches\n\nFixed in `@feathersjs/commons@5.0.45`. The fix skips `__proto__`, `constructor`, and `prototype` keys during iteration — the standard remediation used by lodash and others.\n\n### Workarounds\n\nAvoid passing JSON-parsed untrusted input through `commons._.merge`. Freezing `Object.prototype` or validating/sanitizing keys upstream also mitigates.\n\n### Credit\n\nReported responsibly by Andrew Ridings (@ridingsa).", + "details": "### Impact\n\nThe `_.merge(target, source)` utility exported by `@feathersjs/commons` recursively merges `source` into `target` by iterating `Object.keys(source)`. When `source` was produced by `JSON.parse` and contains a `__proto__` (or `constructor` / `prototype`) key, that key is returned as an own-enumerable property. The recursive merge then resolves `target['__proto__']` to `Object.prototype` and writes the attacker-supplied properties onto it, polluting the prototype for all plain objects in the process for the lifetime of the Node process.\n\n**Scope of real-world risk is limited.** No first-party Feathers package routes input \u2014 trusted or untrusted \u2014 through `commons._.merge`. The `@feathersjs/authentication` package, which does merge request-influenced data, uses `lodash/merge` (prototype-pollution-safe since 4.17.12), not this utility. Exploitation therefore requires a downstream plugin or application to pass JSON-parsed, attacker-controlled input directly through the exported `_.merge`.\n\n### Patches\n\n- **Feathers 5 (Dove):** fixed in `@feathersjs/commons@5.0.45` via https://github.com/feathersjs/feathers/pull/3690\n- **Feathers 4 (Crow):** fixed in `@feathersjs/commons@4.5.20` via https://github.com/feathersjs/feathers/pull/3695\n\nThe fix skips `__proto__`, `constructor`, and `prototype` keys during iteration \u2014 the standard remediation used by lodash and others.\n\nRecommended install targets:\n- Crow / Feathers 4: `@feathersjs/commons@4.5.21` or later (4.5.20 contains this security fix; 4.5.21 is the preferred Crow monorepo release)\n- Dove / Feathers 5: `@feathersjs/commons@5.0.45` or later\n\n### Workarounds\n\nAvoid passing JSON-parsed untrusted input through `commons._.merge`. Freezing `Object.prototype` or validating/sanitizing keys upstream also mitigates.\n\n### Credit\n\nReported responsibly by Andrew Ridings (@ridingsa).\n", "severity": [ { "type": "CVSS_V3", @@ -25,7 +25,29 @@ "type": "ECOSYSTEM", "events": [ { - "introduced": "0" + "introduced": "4.0.0" + }, + { + "fixed": "4.5.20" + } + ] + } + ], + "database_specific": { + "last_known_affected_version_range": "<= 4.5.19" + } + }, + { + "package": { + "ecosystem": "npm", + "name": "@feathersjs/commons" + }, + "ranges": [ + { + "type": "ECOSYSTEM", + "events": [ + { + "introduced": "5.0.0" }, { "fixed": "5.0.45" @@ -51,6 +73,14 @@ "type": "WEB", "url": "https://github.com/feathersjs/feathers/commit/28b3c03c63bdbff53115fdaa46c56980e7942acc" }, + { + "type": "WEB", + "url": "https://github.com/feathersjs/feathers/pull/3695" + }, + { + "type": "WEB", + "url": "https://github.com/feathersjs/feathers/commit/88794cc432ce09e5559780545faa8134359abcce" + }, { "type": "PACKAGE", "url": "https://github.com/feathersjs/feathers" @@ -58,6 +88,14 @@ { "type": "WEB", "url": "https://github.com/feathersjs/feathers/releases/tag/v5.0.45" + }, + { + "type": "WEB", + "url": "https://github.com/feathersjs/feathers/releases/tag/v4.5.20" + }, + { + "type": "WEB", + "url": "https://github.com/feathersjs/feathers/releases/tag/v4.5.21" } ], "database_specific": { @@ -69,4 +107,4 @@ "github_reviewed_at": "2026-07-14T19:40:05Z", "nvd_published_at": null } -} \ No newline at end of file +}