|  | 3 years ago | |
|---|---|---|
| .. | ||
| .github | 3 years ago | |
| benchmarks | 3 years ago | |
| test | 3 years ago | |
| types | 3 years ago | |
| .airtap.yml | 3 years ago | |
| LICENSE.md | 3 years ago | |
| README.md | 3 years ago | |
| index.js | 3 years ago | |
| package.json | 3 years ago | |
		
			
				
				README.md
			
		
		
			
			
		
	
	secure-json-parse
JSON.parse() drop-in replacement with prototype poisoning protection.
Introduction
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.
Install
npm i secure-json-parse
Usage
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.prototype 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' }))
API
sjson.parse(text, [reviver], [options])
Parses a given JSON-formatted text into an object where:
- text- the JSON text string.
- reviver- the- JSON.parse()optional- reviverargument.
- options- optional configuration object where:- protoAction- optional string with one of:- 'error'- throw a- SyntaxErrorwhen 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 calling- JSON.parse()directly).
 
- constructorAction- optional string with one of:- 'error'- throw a- SyntaxErrorwhen a- constructor.prototypekey is found. This is the default value.
- 'remove'- deletes any- constructorkeys from the result object.
- 'ignore'- skips all validation (same as calling- JSON.parse()directly).
 
 
sjson.scan(obj, [options])
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 a- SyntaxErrorwhen a- __proto__key is found. This is the default value.
- 'remove'- deletes any- __proto__keys from the input- obj.
 
- constructorAction- optional string with one of:- 'error'- throw a- SyntaxErrorwhen a- constructor.prototypekey is found. This is the default value.
- 'remove'- deletes any- constructorkeys from the input- obj.
 
 
Benchmarks
Machine: 2,7 GHz Quad-Core Intel Core i7
v14.8.0
> node ignore.js
JSON.parse x 679,376 ops/sec ±1.15% (84 runs sampled)
secure-json-parse x 649,605 ops/sec ±0.58% (87 runs sampled)
reviver x 244,414 ops/sec ±1.05% (88 runs sampled)
Fastest is JSON.parse
> node no__proto__.js
JSON.parse x 652,190 ops/sec ±0.67% (86 runs sampled)
secure-json-parse x 589,785 ops/sec ±1.01% (88 runs sampled)
reviver x 218,075 ops/sec ±1.58% (87 runs sampled)
Fastest is JSON.parse
> node remove.js
JSON.parse x 683,527 ops/sec ±0.62% (88 runs sampled)
secure-json-parse x 316,926 ops/sec ±0.63% (87 runs sampled)
reviver x 214,167 ops/sec ±0.63% (86 runs sampled)
Fastest is JSON.parse
> node throw.js
JSON.parse x 682,548 ops/sec ±0.60% (88 runs sampled)
JSON.parse error x 170,716 ops/sec ±0.93% (87 runs sampled)
secure-json-parse x 104,483 ops/sec ±0.62% (87 runs sampled)
reviver x 114,197 ops/sec ±0.63% (87 runs sampled)
Fastest is JSON.parse
Acknowledgements
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.
License
Licensed under BSD-3-Clause.