JSON.parse()
drop-in replacement with prototype poisoning protection.
Consider this:
> const a = '{"__proto__":{ "b":5}}';
'{"__proto__":{ "b":5}}'
> const b = JSON.parse(a);
{ __proto__: { b: 5 } }
> b.b;
undefined
> const c = Object.assign({}, b);
{}
> c.b
5
The problem is that JSON.parse()
retains the __proto__
property as a plain object key. By
itself, this is not a security issue. However, as soon as that object is assigned to another or
iterated on and values copied, the __proto__
property leaks and becomes the object's prototype.
npm install secure-json-parse
Pass the option object as a second (or third) parameter for configuring the action to take in case of a bad JSON, if nothing is configured, the default is to throw a SyntaxError
.
You can choose which action to perform in case __proto__
is present, and in case constructor
is present.
const sjson = require('secure-json-parse')
const goodJson = '{ "a": 5, "b": 6 }'
const badJson = '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "constructor": {"prototype": {"bar": "baz"} } }'
console.log(JSON.parse(goodJson), sjson.parse(goodJson, { protoAction: 'remove', constructorAction: 'remove' }))
console.log(JSON.parse(badJson), sjson.parse(badJson, { protoAction: 'remove', constructorAction: 'remove' }))
Parses a given JSON-formatted text into an object where:
text
- the JSON text string.reviver
- theJSON.parse()
optionalreviver
argument.options
- optional configuration object where:protoAction
- optional string with one of:'error'
- throw aSyntaxError
when a__proto__
key is found. This is the default value.'remove'
- deletes any__proto__
keys from the result object.'ignore'
- skips all validation (same as callingJSON.parse()
directly).
constructorAction
- optional string with one of:'error'
- throw aSyntaxError
when aconstructor
key is found. This is the default value.'remove'
- deletes anyconstructor
keys from the result object.'ignore'
- skips all validation (same as callingJSON.parse()
directly).
Scans a given object for prototype properties where:
obj
- the object being scanned.options
- optional configuration object where:protoAction
- optional string with one of:'error'
- throw aSyntaxError
when a__proto__
key is found. This is the default value.'remove'
- deletes any__proto__
keys from the inputobj
.
constructorAction
- optional string with one of:'error'
- throw aSyntaxError
when aconstructor
key is found. This is the default value.'remove'
- deletes anyconstructor
keys from the inputobj
.
This project has been forked from hapijs/bourne. All the credits before the commit 4690682 goes to the hapijs/bourne project contributors. After, the project will be maintained by the Fastify team.
Licensed under BSD-3-Clause.