JSONata arbitrary-code-execution trio (CVE-2026-77413 / -77414 / -77415)
Summary
Three critical arbitrary code execution flaws in JSONata (npm, ~1.65M downloads/week, MIT-licensed query and transformation language originating at IBM) were published to the GitHub Advisory Database on August 21, 2026 with working public PoCs. A crafted JSONata expression — evaluated against attacker-controlled or attacker-influenced data — executes attacker code in the host Node.js process via child_process.execSync.
All three advisories describe the same attack class (sandbox-escaping through JSONata's host-object bridge) reached through different primitives:
| Advisory | Root cause | Fixed in |
|---|---|---|
| CVE-2026-77413 / GHSA-8gq3-vp5j-2grp | Missing hasOwnProperty check in the lookup function (src/functions.js, ~L1686–1705) — prototype-chain lookup reaches __lookupSetter__/__defineGetter__ and the object constructor |
2.2.0 (PR #794), backported to 1.8.8 |
| CVE-2026-77414 / GHSA-2943-5xfg-gq5f | Bypassable hasOwnProperty check in environment.lookup (src/jsonata.js, ~L1863–1871) — $hasOwnProperty := $spread($string); $__proto__ := $constructor; recovers the host Function constructor |
2.2.1 (PR #799), backported to 1.8.8 |
| CVE-2026-77415 / GHSA-66mm-25pp-rfff | Chain of three flaws: overwriting $clone (mutating objects via evaluateTransformExpression), destructuring JSONata lambdas (e.g. $merge.*), and applyProcedure using proc.arguments.forEach instead of Array.prototype.forEach |
2.2.1 (PRs #799, #800, #802), backported to 1.8.8 |
Affected: npm jsonata < 1.8.8 and >= 2.0.0 < 2.2.1. All three PoCs end in the same primitive — building a host Function constructor and calling it with "return process.getBuiltinModule('child_process').execSync('sh',{stdio:'inherit'})" (Node 22+; on older Node the equivalent is require('child_process') via the recovered constructor). All three advisories list CWE-94 (Code Injection) and critical severity; no in-the-wild exploitation or actor attribution is reported.
Tags
- tools
- jsonata
- npm
- Node.js
- JavaScript
- code injection
- sandbox escape
- prototype pollution
- host RCE
- critical vulnerability
- CVE-2026-77413
- CVE-2026-77414
- CVE-2026-77415
- GHSA-8gq3-vp5j-2grp
- GHSA-2943-5xfg-gq5f
- GHSA-66mm-25pp-rfff
- GitHub Security Advisories
Why this matters
- JSONata is a data-query language, not a JS sandbox: it is embedded in ETL pipelines, ESB/integration layers, BI and data-catalog tooling, IoT/telemetry decoders, and workflow engines to parse, shape, and transform JSON — often against payloads whose structure is attacker-influenced (device telemetry, API responses, file contents, user-supplied documents). Any of those hosts that also evaluates the expression from user- or pipeline-controlled input is a code-injection surface, not just a data-processing step.
- The three advisories show the host-object bridge (property lookup, lambda/function objects, transform procedures) is the load-bearing trust boundary in JSONata, and that fixing one bypass (2.2.0, May 14) left the next one (2.2.1, May 19 / July backport, August 21 publication) behind it. The pattern — repeated prototype-access bypasses in a data language's object-lookup path — is the same failure family as vm2's wildcard builtins and isolated-vm's native-binding handoff: a "safe" data/query layer whose glue code reaches into host objects.
- Public PoCs exist for all three, and the fixes are ordinary version bumps, so this is a patch-now item: no exploit configuration or network position needed, and no in-the-wild window to wait out.
Mechanism
All three chains use JSONata's ability to reach host JavaScript objects from inside an expression and call methods on them:
CVE-2026-77413 (lookup, fixed in 2.2.0 / 1.8.8). The lookup function in src/functions.js read a key off an object without a hasOwnProperty guard, so the expression engine would walk the prototype chain and expose __lookupSetter__('__proto__') and friends:
jsonata(`(
__lookupSetter__('__proto__')(constructor);
__defineGetter__('l', constructor("return
process.getBuiltinModule('child_process').execSync('sh',{stdio:'inherit'}).toString()"));
valueOf().l
)`).evaluate({});
PR #794 (in 2.2.0, ported into 1.8.8) adds the missing own-property check.
CVE-2026-77414 (environment.lookup bypass, fixed in 2.2.1 / 1.8.8). The analogous check in environment.lookup (src/jsonata.js) was bypassable by spreading the $string function to re-bind $hasOwnProperty and capturing $constructor first:
jsonata(`(
$hasOwnProperty := $spread($string);
$__proto__ := $constructor;
$constructor("return
process.getBuiltinModule('child_process').execSync('sh',{stdio:'inherit'})")();
)`).evaluate({});
PR #799 (in 2.2.1, back-ported to 1.8.8) closes it.
CVE-2026-77415 (transform/lambda/procedure chain, fixed in 2.2.1 / 1.8.8). Three stacked flaws:
1. overwriting $clone allows mutation of objects passed through transforms (evaluateTransformExpression);
2. JSONata functions/lambdas can be destructured (e.g. $merge.*), leaking their internal representation;
3. applyProcedure calls proc.arguments.forEach instead of Array.prototype.forEach, so a poisoned arguments object's forEach is invoked with attacker control.
The published PoC chains them to capture a __lookupGetter__ reference on a transform argument, reconstitutes a host function, and executes child_process.execSync the same way. Fixed by PRs #799, #800, and #802 (in 2.2.1, back-ported to 1.8.8).
Affected and patched versions
| Product | Affected | Patched |
|---|---|---|
| jsonata (npm) v1 line | <= 1.8.7 | 1.8.8 (dist-tag latest-v1 is now 1.8.9) |
| jsonata (npm) v2 line | >= 2.0.0 < 2.2.1 | 2.2.1 (dist-tag latest is now 2.2.2) |
Release timeline on npm: 2.2.0 (2026-05-14, contains PR #794 for 77413), 2.2.1 (2026-05-19, contains PRs #799/#800/#802 for 77414/77415), 1.8.8 (2026-07-16, "Security Release" — prototype-pollution fixes and v1 backports of the same PRs), 2.2.2 (2026-07-16, maintenance), 1.8.9 (2026-07-30, backports $toMillis fixes). The August 21 advisories retroactively assigned the CVEs to those fixes; 2.2.2 / 1.8.9 are the safe targets.
Upgrade notes
- Move to jsonata ≥ 2.2.2 (or ≥ 1.8.9 on the v1 line). Verify the resolved version in
package.json, lockfiles, andnode_modules/jsonata/package.json. - No embedder-side configuration mitigates this: the flaw is reachable by evaluating any attacker-influenced expression on vulnerable versions. If upgrading is not immediately possible, stop evaluating expressions (or the data they bind to) from untrusted input until you are on a patched release.
- Audit where expression strings come from in your pipeline: the risk is expression injection, so a "static" expression evaluated over malicious data is safe, but a template with interpolated user input is not.
Detection
- Dependency sweep:
jsonata < 2.2.1 / < 1.8.8in any Node host that evaluates expressions over external data (ETL/ELT jobs, integration brokers, BI front-ends, workflow engines). - Review expression-provenance code paths: any string built from user/pipeline input and passed to
jsonata(...).evaluate()is the exposure to prioritize. - Host telemetry:
child_process.execSync/ shell spawns from a long-running Node data-pipeline process that has no legitimate reason to exec is the observable half-signature of these PoCs.
Assessment limits
- No in-the-wild exploitation, PoC abuse, or actor linkage is reported as of the August 21, 2026 advisory publication.
- The CVEs were assigned retroactively to fixes that shipped in May–July 2026 (2.2.0, 2.2.1, 1.8.8); the advisories are a disclosure of those fixes with PoCs, not a new exploit window opened in August.
- The PoCs target Node 22+ (
process.getBuiltinModule); equivalentrequire('child_process')access is trivially available on earlier Node lines, so the PoC text should not be read as limiting the impact.
Related pages
- vm2 NodeVM host state exposure and DNS hijack
- isolated-vm ExternalCopy type-confusion sandbox escape
- Agentic workflow trust-boundary failures
Sources
- GitHub: CVE-2026-77413 / GHSA-8gq3-vp5j-2grp — JSONata arbitrary code execution via missing hasOwnProperty check in lookup — published 2026-08-21
- GitHub: CVE-2026-77414 / GHSA-2943-5xfg-gq5f — JSONata arbitrary code execution via bypassable hasOwnProperty check in environment.lookup — published 2026-08-21
- GitHub: CVE-2026-77415 / GHSA-66mm-25pp-rfff — JSONata arbitrary code execution via $clone overwrite, lambda destructuring, and applyProcedure forEach — published 2026-08-21
- Repository: jsonata-js/jsonata (npm
jsonata; fixes in PRs #794, #799, #800, #802; releases 1.8.8 / 2.2.0 / 2.2.1)