{"id":"GHSA-w48f-fwg7-ww6p","aliases":[],"url":"https://o3.security/vulnerability/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.","published":"2026-04-04T04:24:27Z","modified":"2026-04-07T14:37:59.936837Z","cvss":null,"epss":null,"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"npm","name":"@stablelib/cbor","fixedVersion":"2.0.3"}],"fix":{"url":"https://github.com/StableLib/stablelib/commit/0f153a63b7552a0e8721f640984113e419015026","label":"StableLib/stablelib@0f153a6"},"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"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-04-07T14:37:59.936837Z"}}