msgpack5 4.2.1 → 4.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/index.js +4 -2
- package/lib/decoder.js +12 -1
- package/package.json +1 -1
- package/test/object-prototype-poisoning.js +49 -0
package/README.md
CHANGED
|
@@ -109,6 +109,7 @@ options:
|
|
|
109
109
|
- `forceFloat64`, a boolean to that forces all floats to be encoded as 64-bits floats. Defaults to false.
|
|
110
110
|
- `compatibilityMode`, a boolean that enables "compatibility mode" which doesn't use str 8 format. Defaults to false.
|
|
111
111
|
- `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.
|
|
112
|
+
- `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.
|
|
112
113
|
|
|
113
114
|
-------------------------------------------------------
|
|
114
115
|
<a name="encode"></a>
|
package/index.js
CHANGED
|
@@ -14,7 +14,9 @@ function msgpack (options) {
|
|
|
14
14
|
options = options || {
|
|
15
15
|
forceFloat64: false,
|
|
16
16
|
compatibilityMode: false,
|
|
17
|
-
disableTimestampEncoding: false // if true, skips encoding Dates using the msgpack timestamp ext format (-1)
|
|
17
|
+
disableTimestampEncoding: false, // if true, skips encoding Dates using the msgpack timestamp ext format (-1)
|
|
18
|
+
// options.protoAction: 'error' (default) / 'remove' / 'ignore'
|
|
19
|
+
protoAction: 'error'
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
function registerEncoder (check, encode) {
|
|
@@ -69,7 +71,7 @@ function msgpack (options) {
|
|
|
69
71
|
|
|
70
72
|
return {
|
|
71
73
|
encode: buildEncode(encodingTypes, options.forceFloat64, options.compatibilityMode, options.disableTimestampEncoding),
|
|
72
|
-
decode: buildDecode(decodingTypes),
|
|
74
|
+
decode: buildDecode(decodingTypes, options),
|
|
73
75
|
register: register,
|
|
74
76
|
registerEncoder: registerEncoder,
|
|
75
77
|
registerDecoder: registerDecoder,
|
package/lib/decoder.js
CHANGED
|
@@ -14,7 +14,7 @@ function IncompleteBufferError (message) {
|
|
|
14
14
|
|
|
15
15
|
util.inherits(IncompleteBufferError, Error)
|
|
16
16
|
|
|
17
|
-
module.exports = function buildDecode (decodingTypes) {
|
|
17
|
+
module.exports = function buildDecode (decodingTypes, options) {
|
|
18
18
|
return decode
|
|
19
19
|
|
|
20
20
|
function getSize (first) {
|
|
@@ -361,6 +361,17 @@ module.exports = function buildDecode (decodingTypes) {
|
|
|
361
361
|
var valueResult = tryDecode(buf, offset)
|
|
362
362
|
if (valueResult) {
|
|
363
363
|
key = keyResult.value
|
|
364
|
+
|
|
365
|
+
if (key === '__proto__') {
|
|
366
|
+
if (options.protoAction === 'error') {
|
|
367
|
+
throw new SyntaxError('Object contains forbidden prototype property')
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (options.protoAction === 'remove') {
|
|
371
|
+
continue
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
364
375
|
result[key] = valueResult.value
|
|
365
376
|
offset += valueResult.bytesConsumed
|
|
366
377
|
totalBytesConsumed += (keyResult.bytesConsumed + valueResult.bytesConsumed)
|
package/package.json
CHANGED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
var test = require('tape').test
|
|
4
|
+
var msgpack = require('../')
|
|
5
|
+
|
|
6
|
+
test('decode throws when object has forbidden __proto__ property', function (t) {
|
|
7
|
+
const encoder = msgpack()
|
|
8
|
+
|
|
9
|
+
const payload = { hello: 'world' }
|
|
10
|
+
Object.defineProperty(payload, '__proto__', {
|
|
11
|
+
value: { polluted: true },
|
|
12
|
+
enumerable: true
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const encoded = encoder.encode(payload)
|
|
16
|
+
|
|
17
|
+
t.throws(() => encoder.decode(encoded), /Object contains forbidden prototype property/)
|
|
18
|
+
t.end()
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('decode ignores forbidden __proto__ property if protoAction is "ignore"', function (t) {
|
|
22
|
+
const encoder = msgpack({ protoAction: 'ignore' })
|
|
23
|
+
|
|
24
|
+
const payload = { hello: 'world' }
|
|
25
|
+
Object.defineProperty(payload, '__proto__', {
|
|
26
|
+
value: { polluted: true },
|
|
27
|
+
enumerable: true
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const decoded = encoder.decode(encoder.encode(payload))
|
|
31
|
+
|
|
32
|
+
t.equal(decoded.polluted, true)
|
|
33
|
+
t.end()
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
test('decode removes forbidden __proto__ property if protoAction is "remove"', function (t) {
|
|
37
|
+
const encoder = msgpack({ protoAction: 'remove' })
|
|
38
|
+
|
|
39
|
+
const payload = { hello: 'world' }
|
|
40
|
+
Object.defineProperty(payload, '__proto__', {
|
|
41
|
+
value: { polluted: true },
|
|
42
|
+
enumerable: true
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
const decoded = encoder.decode(encoder.encode(payload))
|
|
46
|
+
|
|
47
|
+
t.equal(decoded.polluted, undefined)
|
|
48
|
+
t.end()
|
|
49
|
+
})
|