JSONata expression can pollute the "Object" prototype
Description
In JSONata before 1.8.7 and 2.0.4, the transform operator allows overriding Object prototype properties, potentially leading to denial of service or remote code execution.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
In JSONata before 1.8.7 and 2.0.4, the transform operator allows overriding Object prototype properties, potentially leading to denial of service or remote code execution.
Vulnerability
Overview
JSONata, a JSON query and transformation language, is vulnerable to prototype pollution via its transform operator in versions 1.4.0 through 1.8.6 and 2.0.0 through 2.0.3 [1][2]. A malicious expression can override properties on the Object constructor and prototype, polluting built-in JavaScript objects [2].
Exploitation
The attack surface includes any application that evaluates user-provided JSONata expressions without sanitization [2]. An attacker can craft a JSONata expression that uses the transform operator to set properties like __proto__ or constructor.prototype, thereby injecting malicious properties that affect all objects [2]. No authentication is required if the expression input is exposed to users.
Impact
Successful exploitation can lead to denial of service, remote code execution, or other unexpected behavior due to the alteration of object prototypes [1][2]. The exact impact depends on how the application uses JSONata and the JavaScript runtime environment.
Mitigation
The issue is patched in JSONata versions 1.8.7 and 2.0.4 [2][3]. Applications evaluating user expressions should update immediately. If updating is not possible, a manual patch (shown in the advisory) can be applied to block writes to prototype and constructor properties [2][4].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
jsonatanpm | >= 1.4.0, < 1.8.7 | 1.8.7 |
jsonatanpm | >= 2.0.0, < 2.0.4 | 2.0.4 |
Affected products
4- osv-coords3 versions
< 37.229.2-r0+ 2 more
- (no CPE)range: < 37.229.2-r0
- (no CPE)range: < 37.229.2-r0
- (no CPE)range: >= 1.4.0, < 1.8.7
- jsonata-js/jsonatav5Range: >= 1.4.0, < 1.8.7
Patches
31d579dbe99c1Prevent writing to the object prototype or constructor (v1 port) (#681)
2 files changed · +35 −1
src/jsonata.js+9 −1 modified@@ -1295,6 +1295,13 @@ var jsonata = (function() { } for(var ii = 0; ii < matches.length; ii++) { var match = matches[ii]; + if (match && (match.isPrototypeOf(result) || match instanceof Object.constructor)) { + throw { + code: "D1010", + stack: (new Error()).stack, + position: expr.position + }; + } // evaluate the update value for each match var update = yield * evaluate(expr.update, match, environment); // update must be an object @@ -1539,7 +1546,7 @@ var jsonata = (function() { if (typeof err.token == 'undefined' && typeof proc.token !== 'undefined') { err.token = proc.token; } - err.position = proc.position; + err.position = proc.position || err.position; } throw err; } @@ -1971,6 +1978,7 @@ var jsonata = (function() { "T1007": "Attempted to partially apply a non-function. Did you mean ${{{token}}}?", "T1008": "Attempted to partially apply a non-function", "D1009": "Multiple key definitions evaluate to same key: {{value}}", + "D1010": "Attempted to access the Javascript object prototype", // Javascript specific "T1010": "The matcher function argument passed to function {{token}} does not return the correct object structure", "T2001": "The left side of the {{token}} operator must evaluate to a number", "T2002": "The right side of the {{token}} operator must evaluate to a number",
test/implementation-tests.js+26 −0 modified@@ -806,6 +806,32 @@ describe("Tests that are specific to a Javascript runtime", () => { }); }); }); + describe("Expressions that attempt to pollute the object prototype", function() { + it("should throw an error with __proto__", async function() { + const expr = jsonata('{} ~> | __proto__ | {"is_admin": true} |'); + expect(function() { + expr.evaluate(); + }) + .to.throw() + .to.deep.contain({ position: 7, code: "D1010" }); + }); + it("should throw an error with __lookupGetter__", async function() { + const expr = jsonata('{} ~> | __lookupGetter__("__proto__")() | {"is_admin": true} |'); + expect(function() { + expr.evaluate(); + }) + .to.throw() + .to.deep.contain({ position: 7, code: "D1010" }); + }); + it("should throw an error with constructor", async function() { + const expr = jsonata('{} ~> | constructor | {"is_admin": true} |'); + expect(function() { + expr.evaluate(); + }) + .to.throw() + .to.deep.contain({ position: 7, code: "D1010" }); + }); + }); }); describe("Test that yield platform specific results", () => {
335d38f6278eCheck for constructor property
2 files changed · +10 −1
src/jsonata.js+1 −1 modified@@ -1293,7 +1293,7 @@ var jsonata = (function() { } for(var ii = 0; ii < matches.length; ii++) { var match = matches[ii]; - if (match && match.isPrototypeOf(result)) { + if (match && (match.isPrototypeOf(result) || match instanceof Object.constructor)) { throw { code: "D1010", stack: (new Error()).stack,
test/implementation-tests.js+9 −0 modified@@ -974,6 +974,15 @@ describe("Tests that are specific to a Javascript runtime", () => { code: "D1010", }); }); + it("should throw an error with constructor", async function() { + const expr = jsonata('{} ~> | constructor | {"is_admin": true} |'); + expect( + expr.evaluate() + ).to.eventually.be.rejected.to.deep.contain({ + position: 7, + code: "D1010", + }); + }); }); });
c907b5e517bbPrevent access to __proto__
2 files changed · +29 −1
src/jsonata.js+9 −1 modified@@ -1293,6 +1293,13 @@ var jsonata = (function() { } for(var ii = 0; ii < matches.length; ii++) { var match = matches[ii]; + if (match && match.isPrototypeOf(result)) { + throw { + code: "D1010", + stack: (new Error()).stack, + position: expr.position + }; + } // evaluate the update value for each match var update = await evaluate(expr.update, match, environment); // update must be an object @@ -1539,7 +1546,7 @@ var jsonata = (function() { if (typeof err.token == 'undefined' && typeof proc.token !== 'undefined') { err.token = proc.token; } - err.position = proc.position; + err.position = proc.position || err.position; } throw err; } @@ -1972,6 +1979,7 @@ var jsonata = (function() { "T1007": "Attempted to partially apply a non-function. Did you mean ${{{token}}}?", "T1008": "Attempted to partially apply a non-function", "D1009": "Multiple key definitions evaluate to same key: {{value}}", + "D1010": "Attempted to access the Javascript object prototype", // Javascript specific "T1010": "The matcher function argument passed to function {{token}} does not return the correct object structure", "T2001": "The left side of the {{token}} operator must evaluate to a number", "T2002": "The right side of the {{token}} operator must evaluate to a number",
test/implementation-tests.js+20 −0 modified@@ -955,6 +955,26 @@ describe("Tests that are specific to a Javascript runtime", () => { }); }); }); + describe("Expressions that attempt to pollute the object prototype", function() { + it("should throw an error with __proto__", async function() { + const expr = jsonata('{} ~> | __proto__ | {"is_admin": true} |'); + expect( + expr.evaluate() + ).to.eventually.be.rejected.to.deep.contain({ + position: 7, + code: "D1010", + }); + }); + it("should throw an error with __lookupGetter__", async function() { + const expr = jsonata('{} ~> | __lookupGetter__("__proto__")() | {"is_admin": true} |'); + expect( + expr.evaluate() + ).to.eventually.be.rejected.to.deep.contain({ + position: 7, + code: "D1010", + }); + }); + }); }); describe("Test that yield platform specific results", () => {
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-fqg8-vfv7-8fj8ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-27307ghsaADVISORY
- github.com/jsonata-js/jsonata/commit/1d579dbe99c19fbe509f5ba2c6db7959b0d456d1ghsax_refsource_MISCWEB
- github.com/jsonata-js/jsonata/commit/335d38f6278e96c908b24183f1c9c90afc8ae00cghsax_refsource_MISCWEB
- github.com/jsonata-js/jsonata/commit/c907b5e517bb718015fcbd993d742ba6202f2be2ghsax_refsource_MISCWEB
- github.com/jsonata-js/jsonata/releases/tag/v2.0.4ghsax_refsource_MISCWEB
- github.com/jsonata-js/jsonata/security/advisories/GHSA-fqg8-vfv7-8fj8ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.