VYPR
Moderate severityNVD Advisory· Published Mar 12, 2021· Updated Aug 3, 2024

Prototype poisoning

CVE-2021-21368

Description

msgpack5 before 3.6.1, 4.5.1, and 5.2.1 has a prototype poisoning vulnerability where decoding a map with key __proto__ can set the decoded object's prototype.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

msgpack5 before 3.6.1, 4.5.1, and 5.2.1 has a prototype poisoning vulnerability where decoding a map with key __proto__ can set the decoded object's prototype.

Vulnerability

msgpack5, a MessagePack implementation for Node.js and browsers, contains a prototype poisoning vulnerability in versions prior to 3.6.1, 4.5.1, and 5.2.1. When decoding a map, if a key is exactly __proto__, the decoder assigns the corresponding value to __proto__. Since Object.prototype.__proto__ is an accessor property that sets the prototype of the receiver, this allows an attacker to change the prototype of the decoded object to any value that can be represented in MessagePack (e.g., an Array, Map, or Date) [1][2].

Exploitation

An attacker who can submit crafted MessagePack data to a service using an affected version can exploit this vulnerability. No authentication or special privileges are required beyond the ability to send data. The attack results in decoded objects whose prototypes are overwritten, causing them to appear as different types. For example, setting __proto__ to a Map makes the decoded object pass instanceof Map checks and exhibit Map-like methods, but using those methods may throw TypeError due to incompatible receivers [2].

Impact

The impact is limited to the decoded object's prototype; the global prototype is not affected. However, this can lead to type confusion, unexpected property access (e.g., length, push if prototype is an Array), and runtime exceptions when the object is used. The vulnerability does not directly enable full prototype pollution, but it can cause unpredictable behavior and potential denial of service [1][2].

Mitigation

The issue has been patched in msgpack5 versions 3.6.1, 4.5.1, and 5.2.1 [3][4]. Users should upgrade to these versions or later. No workarounds are mentioned; the advisory recommends updating promptly.

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
msgpack5npm
< 3.6.13.6.1
msgpack5npm
>= 4.0.0, < 4.5.14.5.1
msgpack5npm
>= 5.0.0, < 5.2.15.2.1

Affected products

2

Patches

1
d4e6cb956ae5

Merge pull request from GHSA-gmjw-49p4-pcfm

https://github.com/mcollina/msgpack5Matteo CollinaMar 5, 2021via ghsa
4 files changed · +64 1
  • index.js+3 1 modified
    @@ -19,7 +19,9 @@ function msgpack (options) {
         // if true, skips encoding Dates using the msgpack
         // timestamp ext format (-1)
         disableTimestampEncoding: false,
    -    preferMap: false
    +    preferMap: false,
    +    // options.protoAction: 'error' (default) / 'remove' / 'ignore'
    +    protoAction: 'error'
       }
     
       decodingTypes.set(DateCodec.type, DateCodec.decode)
    
  • lib/decoder.js+11 0 modified
    @@ -187,6 +187,17 @@ module.exports = function buildDecode (decodingTypes, options) {
           for (let i = 0; i < 2 * length; i += 2) {
             const key = result[i]
             const val = result[i + 1]
    +
    +        if (key === '__proto__') {
    +          if (options.protoAction === 'error') {
    +            throw new SyntaxError('Object contains forbidden prototype property')
    +          }
    +
    +          if (options.protoAction === 'remove') {
    +            continue
    +          }
    +        }
    +
             object[key] = val
           }
           return [object, consumedBytes]
    
  • README.md+1 0 modified
    @@ -111,6 +111,7 @@ options:
     - `compatibilityMode`, a boolean that enables "compatibility mode" which doesn't use str 8 format. Defaults to false.
     - `disableTimestampEncoding`, a boolean that when set disables the encoding of Dates into the [timestamp extension type](https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type). Defaults to false.
     - `preferMap`, a boolean that forces all maps to be decoded to `Map`s rather than plain objects. This ensures that `decode(encode(new Map())) instanceof Map` and that iteration order is preserved. Defaults to false.
    +- `protoAction`, a string which can be `error|ignore|remove` that determines what happens when decoding a plain object with a `__proto__` property which would cause prototype poisoning. `error` (default) throws an error, `remove` removes the property, `ignore` (not recommended) allows the property, thereby causing prototype poisoning on the decoded object.
     
     -------------------------------------------------------
     <a name="encode"></a>
    
  • test/object-prototype-poisoning.js+49 0 added
    @@ -0,0 +1,49 @@
    +'use strict'
    +
    +var test = require('tape').test
    +var msgpack = require('../')
    +
    +test('decode throws when object has forbidden __proto__ property', function (t) {
    +  const encoder = msgpack()
    +
    +  const payload = { hello: 'world' }
    +  Object.defineProperty(payload, '__proto__', {
    +    value: { polluted: true },
    +    enumerable: true
    +  })
    +
    +  const encoded = encoder.encode(payload)
    +
    +  t.throws(() => encoder.decode(encoded), /Object contains forbidden prototype property/)
    +  t.end()
    +})
    +
    +test('decode ignores forbidden __proto__ property if protoAction is "ignore"', function (t) {
    +  const encoder = msgpack({ protoAction: 'ignore' })
    +
    +  const payload = { hello: 'world' }
    +  Object.defineProperty(payload, '__proto__', {
    +    value: { polluted: true },
    +    enumerable: true
    +  })
    +
    +  const decoded = encoder.decode(encoder.encode(payload))
    +
    +  t.equal(decoded.polluted, true)
    +  t.end()
    +})
    +
    +test('decode removes forbidden __proto__ property if protoAction is "remove"', function (t) {
    +  const encoder = msgpack({ protoAction: 'remove' })
    +
    +  const payload = { hello: 'world' }
    +  Object.defineProperty(payload, '__proto__', {
    +    value: { polluted: true },
    +    enumerable: true
    +  })
    +
    +  const decoded = encoder.decode(encoder.encode(payload))
    +
    +  t.equal(decoded.polluted, undefined)
    +  t.end()
    +})
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

0

No linked articles in our index yet.