51 lines
1.6 KiB
Markdown
51 lines
1.6 KiB
Markdown
# Bourne. JSON Bourne.
|
|
|
|
`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.
|
|
|
|
## API
|
|
|
|
### `Bourne.parse(text, [reviver], [options])`
|
|
|
|
Parses a given JSON-formatted text into an object where:
|
|
- `text` - the JSON text string.
|
|
- `reviver` - the `JSON.parse()` optional `reviver` argument.
|
|
- `options` - optional configuration object where:
|
|
- `protoAction` - optional string with one of:
|
|
- `'error'` - throw a `SyntaxError` 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 calling `JSON.parse()` directly).
|
|
|
|
### `Bourne.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 `SyntaxError` when a `__proto__` key is found. This is the default value.
|
|
- `'remove'` - deletes any `__proto__` keys from the input `obj`.
|