A complete implementation of JSON Pointer (RFC 6901) for nodejs and modern browsers.
Installations
npm install json-ptr
Releases
Unable to fetch releases
Developer
flitbit
Developer Guide
Module System
CommonJS, ESM, UMD
Min. Node Version
Typescript Support
Yes
Node Version
14.18.2
NPM Version
6.14.15
Statistics
93 Stars
201 Commits
28 Forks
4 Watching
6 Branches
8 Contributors
Updated on 16 Oct 2024
Languages
TypeScript (95.22%)
JavaScript (2.77%)
HTML (2.02%)
Total Downloads
Cumulative downloads
Total Downloads
91,144,229
Last day
-4.9%
102,093
Compared to previous day
Last week
2.2%
563,102
Compared to previous week
Last month
4.7%
2,362,649
Compared to previous month
Last year
9.6%
25,800,095
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Dev Dependencies
39
json-ptr
A complete implementation of JSON Pointer (RFC 6901) for nodejs and modern browsers.
Supports Relative JSON Pointers. (Example)
Background
I wrote this a few years back when I was unable to find a complete implementation of RFC 6901. It turns out that I now use the hell out of it. I hope you also find it useful.
Install
1npm install json-ptr
Release Bundles
As of v3.0.0, we provide CJS, ESM, and UMD builds under the dist/
folder when you install the package from NPM, we also have all appropriate references in our package.json
file, so your code should just work. If you need a CDN reference for a website or the like, try UNPKG, which picks up our releases automatically.
CDN: https://unpkg.com/browse/json-ptr@3.1.0/dist/json-ptr.min.js.
Use
Both CJS and ESM are supported.
1const { JsonPointer } = require('json-ptr');
1import { JsonPointer } from 'json-ptr';
API Documentation
The API documentation is generated from code by typedoc and hosted here. Read the docs.
Documentation is always a work in progress, let us know by creating an issue if you need a scenario documented.
Example
There are many uses for JSON Pointers, here's one we encountered when we updated a public API and suddenly had clients sending two different message bodies to our APIs. This example is contrived to illustrate how we supported both new and old incoming messages:
1// examples/versions.ts 2import { JsonPointer } from 'json-ptr'; 3 4export type SupportedVersion = '1.0' | '1.1'; 5 6interface PrimaryGuestNamePointers { 7 name: JsonPointer; 8 surname: JsonPointer; 9 honorific: JsonPointer; 10} 11const versions: Record<SupportedVersion, PrimaryGuestNamePointers> = { 12 '1.0': { 13 name: JsonPointer.create('/guests/0/name'), 14 surname: JsonPointer.create('/guests/0/surname'), 15 honorific: JsonPointer.create('/guests/0/honorific'), 16 }, 17 '1.1': { 18 name: JsonPointer.create('/primary/primaryGuest/name'), 19 surname: JsonPointer.create('/primary/primaryGuest/surname'), 20 honorific: JsonPointer.create('/primary/primaryGuest/honorific'), 21 }, 22}; 23 24interface Reservation extends Record<string, unknown> { 25 version?: SupportedVersion; 26} 27 28/** 29 * Gets the primary guest's name from the specified reservation. 30 * @param reservation a reservation, either version 1.0 or bearing a `version` 31 * property indicating the version. 32 */ 33function primaryGuestName(reservation: Reservation): string { 34 const pointers = versions[reservation.version || '1.0']; 35 if (!pointers) { 36 throw new Error(`Unsupported reservation version: ${reservation.version}`); 37 } 38 const name = pointers.name.get(reservation) as string; 39 const surname = pointers.surname.get(reservation) as string; 40 const honorific = pointers.honorific.get(reservation) as string; 41 const names: string[] = []; 42 if (honorific) names.push(honorific); 43 if (name) names.push(name); 44 if (surname) names.push(surname); 45 return names.join(' '); 46} 47 48// The original layout of a reservation (only the parts relevant to our example) 49const reservationV1: Reservation = { 50 guests: [ 51 { 52 name: 'Wilbur', 53 surname: 'Finkle', 54 honorific: 'Mr.', 55 }, 56 { 57 name: 'Wanda', 58 surname: 'Finkle', 59 honorific: 'Mrs.', 60 }, 61 { 62 name: 'Wilma', 63 surname: 'Finkle', 64 honorific: 'Miss', 65 child: true, 66 age: 12, 67 }, 68 ], 69 // ... 70}; 71 72// The new layout of a reservation (only the parts relevant to our example) 73const reservationV1_1: Reservation = { 74 version: '1.1', 75 primary: { 76 primaryGuest: { 77 name: 'Wilbur', 78 surname: 'Finkle', 79 honorific: 'Mr.', 80 }, 81 additionalGuests: [ 82 { 83 name: 'Wanda', 84 surname: 'Finkle', 85 honorific: 'Mrs.', 86 }, 87 { 88 name: 'Wilma', 89 surname: 'Finkle', 90 honorific: 'Miss', 91 child: true, 92 age: 12, 93 }, 94 ], 95 // ... 96 }, 97 // ... 98}; 99 100console.log(primaryGuestName(reservationV1)); 101console.log(primaryGuestName(reservationV1_1));
Security Vulnerabilities (Resolved)
-
prior to v3.0.0 there was a security vulnerability which allowed a developer to perform prototype pollution by sending malformed path segments to
json-ptr
. If you were one of these developers, you should upgrade to v3.0.0 immediately, and stop usingjson-ptr
to pollute an object's prototype. If you feel you have a legitimate reason to do so, please use another method and leavejson-ptr
out of it. Such behavior has been disallowed since it can easily be done using plain ol javascript by those determined to violate common best practice. -
prior to v2.1.0 there was a security vulnerability which allowed an unscrupulous actor to execute arbitrary code if developers failed to sanitize user input before sending it to
json-ptr
. If your code does not sanitize user input before sending it tojson-ptr
, your project is vulnerable and you should upgrade to v3.0.0 immediately. And while your at it, start sanitized user input before sending it to any library!
Breaking Changes at v1.3.0
As was rightly pointed out in this issue, I should have rolled the major version at v1.3.0
instead of the minor version due to breaking changes to the API. Not the worst blunder I've made, but my apologies all the same. Since the ship has sailed, I'm boosting the visibility of these breaking changes.
Where did the Global Functions Go?
In version v1.3.0
of the library, global functions were moved to static functions of the JsonPointer
class. There should be no difference in arguments or behavior. If you were previously importing the global functions it is a small change to destructure them and have compatible code.
Tests
We're maintaining near 100% test coverage. Visit our circleci build page and drill down on a recent build's build and test step to see where we're at. It should look something like:
1=============================== Coverage summary =============================== 2Statements : 100% ( 270/270 ) 3Branches : 100% ( 172/172 ) 4Functions : 100% ( 49/49 ) 5Lines : 100% ( 265/265 ) 6================================================================================
We use mocha so you can also clone the code and:
1$ npm install 2$ npm test
Once you've run the tests on the command line you can open up ./tests.html in the browser of your choice.
Performance
WARNING! These performance metrics are quite outdated. We'll be updating as soon as we have time.
This repository has a companion repository that makes some performance comparisons between json-ptr
, jsonpointer
and json-pointer
.
All timings are expressed as nanoseconds:
1.flatten(obj) 2... 3MODULE | METHOD | COMPILED | SAMPLES | AVG | SLOWER 4json-pointer | dict | | 10 | 464455181 | 5json-ptr | flatten | | 10 | 770424039 | 65.88% 6jsonpointer | n/a | | - | - | 7 8.has(obj, pointer) 9... 10MODULE | METHOD | COMPILED | SAMPLES | AVG | SLOWER 11json-ptr | has | compiled | 1000000 | 822 | 12json-ptr | has | | 1000000 | 1747 | 112.53% 13json-pointer | has | | 1000000 | 2683 | 226.4% 14jsonpointer | n/a | | - | - | 15 16.has(obj, fragmentId) 17... 18MODULE | METHOD | COMPILED | SAMPLES | AVG | SLOWER 19json-ptr | has | compiled | 1000000 | 602 | 20json-ptr | has | | 1000000 | 1664 | 176.41% 21json-pointer | has | | 1000000 | 2569 | 326.74% 22jsonpointer | n/a | | - | - | 23 24.get(obj, pointer) 25... 26MODULE | METHOD | COMPILED | SAMPLES | AVG | SLOWER 27json-ptr | get | compiled | 1000000 | 590 | 28json-ptr | get | | 1000000 | 1676 | 184.07% 29jsonpointer | get | compiled | 1000000 | 2102 | 256.27% 30jsonpointer | get | | 1000000 | 2377 | 302.88% 31json-pointer | get | | 1000000 | 2585 | 338.14% 32 33.get(obj, fragmentId) 34... 35MODULE | METHOD | COMPILED | SAMPLES | AVG | SLOWER 36json-ptr | get | compiled | 1000000 | 587 | 37json-ptr | get | | 1000000 | 1673 | 185.01% 38jsonpointer | get | compiled | 1000000 | 2105 | 258.6% 39jsonpointer | get | | 1000000 | 2451 | 317.55% 40json-pointer | get | | 1000000 | 2619 | 346.17% 41
These results have been elided because there is too much detail in the actual. Your results will vary slightly depending on the resources available where you run it.
It is important to recognize in the performance results that compiled options are faster. As a general rule, you should compile any pointers you'll be using repeatedly.
Releases
-
2022-02-02 — 3.1.0
- fixed issue #48 wherein, when calling any of the
.set()
methods, which in turn rely onsetValueAtPath()
, and using theforce
argument to enable creating an object graph, one character path segments were interpreted as numbers, which resulted in unintended object graphs being created when the character was not an integer. - fixed borked documentation as reported in issue #44
- fixed issue #48 wherein, when calling any of the
-
2021-10-26 — 3.0.0 Potential Security Vulnerability Patched
- When setting a value on an object graph, a developer could purposely use
json-ptr
to pollute an object's prototype by passing invalid path segments to the set/unset operations. This behavior has been disallowed.
- When setting a value on an object graph, a developer could purposely use
-
2021-05-14 — 2.2.0 Added Handling for Relative JSON Pointers
-
2021-05-12 — 2.1.1 Bug fix for #36
- @CarolynWebster reported an unintentional behavior change starting at v1.3.0. An operation involving a pointer/path that crossed a null value in the object graph resulted in an exception. In versions prior to v1.3.0 it returned
undefined
as intended. The original behavior has been restored.
- @CarolynWebster reported an unintentional behavior change starting at v1.3.0. An operation involving a pointer/path that crossed a null value in the object graph resulted in an exception. In versions prior to v1.3.0 it returned
-
2021-05-12 — 2.1.0 Bug fixes for #28 and #30; Security Vulnerability Patched
-
When compiling the accessors for quickly accessing points in an object graph, the
.get()
method was not properly delimiting single quotes. This error caused the get operation to throw an exception in during normal usage. Worse, in cases where malicious user input was sent directly tojson-ptr
, the failure to delimit single quotes allowed the execution of arbitrary code (an injection attack). The first of these issues was reported in #28 by @mprast, the second (vulnerability) by @zpbrent. Thanks also to @elimumford for the actual code used for the fix. -
If your code sent un-sanitized user input to the
.get()
method ofjson-ptr
, your project was susceptible to this security vulnerability!
-
-
2020-10-21 — 2.0.0 Breaking Change
- Prototype pollution using this library is now disallowed and will throw an error. I've been looking into the origin of this issue and it seems to have been disclosed by mohan on huntr.dev. I received a PR from @luci-m-666, but found another PR by @alromh87 that looks like the origin of the solution. Don't know who to thank, but thanks all -- somebody is due a bounty.
- Just in case somebody was relying on
json-ptr
to support pointers across the prototype, I'm rolling the major version number because you're now broken.
BEWARE of Breaking Changes at v1.3.0!
-
2020-07-20 — 1.3.2
- Added missing
tslib
dependency. - Documented where the global functions are now located; moving them broke compatibility at v1.3.0.
- Added missing
-
2020-07-10 — 1.3.0 BREAKING CHANGES
- BREAKING CHANGE: Global functions are now static functions on the
JsonPointer
type. See Where did the Global Functions Go? - Merged new
.unset()
function contributed by @chrishalbert, updated dependencies. - Migrated to typescript and retooled build/test/deploy pipeline. Definitely typed.
- 100% test coverage which illuminated some idiosyncrasies; maybe we killed unobserved bugs, nobody knows.
- BREAKING CHANGE: Global functions are now static functions on the
-
2019-09-14 — 1.2.0
- Merged new
.concat
function contributed by @vuwuv, updated dependencies.
- Merged new
-
2019-03-10 — 1.1.2
- Updated packages to remove critical security concern among dev dependencies'
-
2016-07-26 — 1.0.1
- Fixed a problem with the Babel configuration
-
2016-01-12 — 1.0.0
- Rolled major version to 1 to reflect breaking change in
.list(obj, fragmentId)
.
- Rolled major version to 1 to reflect breaking change in
-
2016-01-02 — 0.3.0
- Retooled for node 4+
- Better compiled pointers
- Unrolled recursive
.list
function - Added
.map
function - Fully linted
- Lots more tests and examples.
- Documented many previously undocumented features.
-
2014-10-21 — 0.2.0 Added #list function to enumerate all properties in a graph, producing fragmentId/value pairs.
License
Stable Version
The latest stable version of the package.
Stable Version
3.1.1
HIGH
2
7.3/10
Summary
Arbitrary Code Execution in json-ptr
Affected Versions
< 2.1.0
Patched Versions
2.1.0
0/10
Summary
Arbitrary Code Execution in json-ptr
Affected Versions
< 2.1.0
Patched Versions
2.1.0
MODERATE
1
5.6/10
Summary
Prototype Pollution in json-ptr
Affected Versions
< 3.0.0
Patched Versions
3.0.0
Reason
no binaries found in the repo
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: MIT License: LICENSE:0
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
Found 1/22 approved changesets -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
branch protection not enabled on development/release branches
Details
- Warn: branch protection not enabled for branch 'main'
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
- Warn: 0 commits out of 13 are checked with a SAST tool
Reason
14 existing vulnerabilities detected
Details
- Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92
- Warn: Project is vulnerable to: GHSA-q765-wm9j-66qj
- Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg
- Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275
- Warn: Project is vulnerable to: GHSA-4q6p-r6v2-jvc5
- Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h
- Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv
- Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3
- Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm
- Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw
- Warn: Project is vulnerable to: GHSA-4wf5-vphf-c2xc
- Warn: Project is vulnerable to: GHSA-hc6q-2mpp-qw7j
- Warn: Project is vulnerable to: GHSA-4vvj-4cpr-p986
- Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7
Score
1.7
/10
Last Scanned on 2024-11-25
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More