{"id":13525697,"url":"https://github.com/fastify/secure-json-parse","last_synced_at":"2025-05-14T08:08:10.401Z","repository":{"id":34837226,"uuid":"184086411","full_name":"fastify/secure-json-parse","owner":"fastify","description":"JSON.parse() drop-in replacement with prototype poisoning protection","archived":false,"fork":false,"pushed_at":"2025-05-01T17:14:39.000Z","size":167,"stargazers_count":231,"open_issues_count":0,"forks_count":17,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-05-01T18:26:42.856Z","etag":null,"topics":["fastify-library","json-parser","security"],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/secure-json-parse","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fastify.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"fastify","open_collective":"fastify"}},"created_at":"2019-04-29T14:27:46.000Z","updated_at":"2025-05-01T17:14:35.000Z","dependencies_parsed_at":"2023-10-14T20:07:00.202Z","dependency_job_id":"bd4b0dda-9275-40e3-9e13-d9d5d0bb549a","html_url":"https://github.com/fastify/secure-json-parse","commit_stats":{"total_commits":172,"total_committers":22,"mean_commits":7.818181818181818,"dds":0.7325581395348837,"last_synced_commit":"370ca288e38279050b5578586066327944b940db"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Fsecure-json-parse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Fsecure-json-parse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Fsecure-json-parse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Fsecure-json-parse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fastify","download_url":"https://codeload.github.com/fastify/secure-json-parse/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254101558,"owners_count":22014908,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastify-library","json-parser","security"],"created_at":"2024-08-01T06:01:21.147Z","updated_at":"2025-05-14T08:08:10.361Z","avatar_url":"https://github.com/fastify.png","language":"JavaScript","readme":"# secure-json-parse\n\n[![CI](https://github.com/fastify/secure-json-parse/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/fastify/secure-json-parse/actions/workflows/ci.yml)\n[![NPM version](https://img.shields.io/npm/v/secure-json-parse.svg?style=flat)](https://www.npmjs.com/package/secure-json-parse)\n[![neostandard javascript style](https://img.shields.io/badge/code_style-neostandard-brightgreen?style=flat)](https://github.com/neostandard/neostandard)\n\n`JSON.parse()` drop-in replacement with prototype poisoning protection.\n\n## Introduction\n\nConsider this:\n\n```js\n\u003e const a = '{\"__proto__\":{ \"b\":5}}';\n'{\"__proto__\":{ \"b\":5}}'\n\n\u003e const b = JSON.parse(a);\n{ __proto__: { b: 5 } }\n\n\u003e b.b;\nundefined\n\n\u003e const c = Object.assign({}, b);\n{}\n\n\u003e c.b\n5\n```\n\nThe problem is that `JSON.parse()` retains the `__proto__` property as a plain object key. By\nitself, this is not a security issue. However, as soon as that object is assigned to another or\niterated on and values copied, the `__proto__` property leaks and becomes the object's prototype.\n\n## Install\n```\nnpm i secure-json-parse\n```\n\n## Usage\n\nPass 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`.\u003cbr/\u003e\nYou can choose which action to perform in case `__proto__` is present, and in case `constructor.prototype` is present.\n\n```js\nconst sjson = require('secure-json-parse')\n\nconst goodJson = '{ \"a\": 5, \"b\": 6 }'\nconst badJson = '{ \"a\": 5, \"b\": 6, \"__proto__\": { \"x\": 7 }, \"constructor\": {\"prototype\": {\"bar\": \"baz\"} } }'\n\nconsole.log(JSON.parse(goodJson), sjson.parse(goodJson, undefined, { protoAction: 'remove', constructorAction: 'remove' }))\nconsole.log(JSON.parse(badJson), sjson.parse(badJson, undefined, { protoAction: 'remove', constructorAction: 'remove' }))\n```\n\n## API\n\n### `sjson.parse(text, [reviver], [options])`\n\nParses a given JSON-formatted text into an object where:\n- `text` - the JSON text string.\n- `reviver` - the `JSON.parse()` optional `reviver` argument.\n- `options` - optional configuration object where:\n    - `protoAction` - optional string with one of:\n        - `'error'` - throw a `SyntaxError` when a `__proto__` key is found. This is the default value.\n        - `'remove'` - deletes any `__proto__` keys from the result object.\n        - `'ignore'` - skips all validation (same as calling `JSON.parse()` directly).\n    - `constructorAction` - optional string with one of:\n        - `'error'` - throw a `SyntaxError` when a `constructor.prototype` key is found. This is the default value.\n        - `'remove'` - deletes any `constructor` keys from the result object.\n        - `'ignore'` - skips all validation (same as calling `JSON.parse()` directly).\n\n### `sjson.scan(obj, [options])`\n\nScans a given object for prototype properties where:\n- `obj` - the object being scanned.\n- `options` - optional configuration object where:\n    - `protoAction` - optional string with one of:\n        - `'error'` - throw a `SyntaxError` when a `__proto__` key is found. This is the default value.\n        - `'remove'` - deletes any `__proto__` keys from the input `obj`.\n    - `constructorAction` - optional string with one of:\n        - `'error'` - throw a `SyntaxError` when a `constructor.prototype` key is found. This is the default value.\n        - `'remove'` - deletes any `constructor` keys from the input `obj`.\n\n## Benchmarks\n\nMachine: 2,7 GHz Quad-Core Intel Core i7\n\n```\nv14.8.0\n\n\u003e node ignore.js\n\nJSON.parse x 679,376 ops/sec ±1.15% (84 runs sampled)\nsecure-json-parse x 649,605 ops/sec ±0.58% (87 runs sampled)\nreviver x 244,414 ops/sec ±1.05% (88 runs sampled)\nFastest is JSON.parse\n\n\u003e node no__proto__.js\n\nJSON.parse x 652,190 ops/sec ±0.67% (86 runs sampled)\nsecure-json-parse x 589,785 ops/sec ±1.01% (88 runs sampled)\nreviver x 218,075 ops/sec ±1.58% (87 runs sampled)\nFastest is JSON.parse\n\n\u003e node remove.js\n\nJSON.parse x 683,527 ops/sec ±0.62% (88 runs sampled)\nsecure-json-parse x 316,926 ops/sec ±0.63% (87 runs sampled)\nreviver x 214,167 ops/sec ±0.63% (86 runs sampled)\nFastest is JSON.parse\n\n\u003e node throw.js\n\nJSON.parse x 682,548 ops/sec ±0.60% (88 runs sampled)\nJSON.parse error x 170,716 ops/sec ±0.93% (87 runs sampled)\nsecure-json-parse x 104,483 ops/sec ±0.62% (87 runs sampled)\nreviver x 114,197 ops/sec ±0.63% (87 runs sampled)\nFastest is JSON.parse\n```\n\n## Acknowledgments\nThis project has been forked from [hapijs/bourne](https://github.com/hapijs/bourne).\nAll credit before commit [4690682](https://github.com/hapijs/bourne/commit/4690682c6cdaa06590da7b2485d5df91c09da889) goes to the hapijs/bourne project contributors.\nAfter, the project will be maintained by the Fastify team.\n\n## License\nLicensed under [BSD-3-Clause](./LICENSE).\n","funding_links":["https://github.com/sponsors/fastify","https://opencollective.com/fastify"],"categories":["JavaScript","Security Hardening"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffastify%2Fsecure-json-parse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffastify%2Fsecure-json-parse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffastify%2Fsecure-json-parse/lists"}