The maintainers of the GJSON Go library have released version 1.9.3 to remediate a high-severity regular expression denial-of-service (ReDoS) flaw, tracked as CVE-2021-42836, that could be exploited by attackers to drive CPU consumption to the point of service unavailability. The patch, committed in October 2021, introduces a match complexity limit that throttles the regular expression engine when processing crafted JSON queries, effectively neutralizing the attack vector.

How the Vulnerability Works

GJSON is a fast, path-based JSON query library for Go, widely embedded in cloud services, command-line tools, and log parsers. Before version 1.9.3, its pattern-matching engine—used by operators like % for string matching—lacked any guardrails on match complexity. An attacker who could supply JSON input and a malicious query pattern could force the library into catastrophic backtracking, where the regular expression engine churns through exponentially many paths, consuming 100% of a CPU core for seconds, minutes, or indefinitely.

The core issue lies in the library’s match routine, a function that evaluates pattern expressions against string values. In pre‑1.9.3 code, this routine was invoked directly during object key parsing and when query operators evaluated string patterns. A carefully constructed JSON document combined with a pathological pattern—exposed through an API, message queue, or even a CLI invocation—could trigger a regular expression match that never terminated in reasonable time. This is classic ReDoS: no crash, no error, just silent resource exhaustion.

The National Vulnerability Database assigns CVE-2021-42836 a CVSS 3.x base score of 7.5 (High), with the attack vector classified as Uncontrolled Resource Consumption (CWE‑400). It requires no privileges, no user interaction, and relies solely on crafted input reaching the vulnerable code path. The impact is strictly on availability; there is no code execution or data leakage.

The Fix: A Cap on Match Complexity

The remedy landed in a single, targeted commit (77a57fda87) that wraps all calls to the unbounded match.Match(...) function with a new matchLimit wrapper. That wrapper enforces a hard cap of 10,000 match operations—enough to handle legitimate queries, but a showstopper for the pathological patterns that fuel ReDoS. The commit changed two critical call sites:

  • In the JSON object parser (parseObject), where keys are matched against a pattern.
  • In the query evaluator (queryMatches), where the % operator applies a pattern to a string value.

By replacing match.Match(...) with matchLimit(...), the library now bails out of overly complex matches, bounding CPU time to a predictable ceiling. The maintainers also added test cases that reproduce the original exploit and verify the fix. This change shipped in the formal v1.9.3 release, and every version since then carries the protection.

Who Needs to Act Now

This vulnerability is not theoretical. Any application that accepts untrusted JSON and uses GJSON queries is at risk. The exposure surface is broad:

  • Public-facing APIs that parse JSON payloads and execute GJSON path expressions.
  • Log aggregators and SIEM tools that accept arbitrary structured data from users or external sources.
  • Command-line utilities (often written in Go) that ingest user-supplied JSON and run path queries.
  • Multi-tenant or PaaS environments where one tenant’s input can affect another’s performance.

Even internal tools that consume JSON from less-than-fully-trusted sources (partner feeds, webhooks, message queues) carry risk. An attacker who can inject a single crafted JSON blob can degrade or take down a service, potentially bypassing authentication if the parser runs before access checks.

If your application merely uses GJSON as a JSON access library for fixed, hardcoded paths (like "name.first") and does not expose query operators to user input, the attack surface shrinks dramatically. But over‑indexing on assumed safe usage is dangerous: dependencies evolve, and a future feature might unwittingly open the door. Treat any instance of GJSON before 1.9.3 as a potential threat until proven otherwise.

What to Do If You Can’t Upgrade Immediately

Upgrading to GJSON v1.9.3 or later is the definitive fix. However, for teams that cannot rebuild and redeploy right away—legacy systems, third‑party containers, or vendor appliances—several mitigations can reduce risk:

  • Input sanitization and query whitelisting. Strip or disallow untrusted pattern operators entirely. If users can supply query strings, pre‑validate them against a strict allowlist of safe expressions.
  • Rate limiting and throttling. Cap the number of JSON‑processing requests per second from a single source. While not preventing ReDoS, it makes sustained attacks harder to execute.
  • Resource sandboxing. Run JSON parsing in a separate process, container, or cgroup with strict CPU limits. If a ReDoS payload triggers, the sandboxed process may stall, but the main service remains available.
  • Application‑level timeouts. Wrap GJSON calls in a context with a deadline. If a gjson.Get() call exceeds, say, 100 ms, return an error and free the goroutine.

These are stopgaps, not solutions. They protect your service’s availability but do not remove the underlying library risk. Use them to buy time while you prepare a proper update.

Checking Whether You’re Affected

Locate every project that imports github.com/tidwall/gjson by running go list -m all or examining your go.mod files. Automated tools can help:

  • govulncheck (the Go team’s official vulnerability scanner) will flag CVE‑2021‑42836 if present.
  • OSV‑scanner and other dependency checkers consume the same OSV database entry.
  • Software Composition Analysis (SCA) tools integrated into CI/CD pipelines can block builds that include the vulnerable version.

For Linux distributions, package names often follow the pattern golang-github-tidwall-gjson-dev. Check your package manager and compare the installed version against the distribution’s security tracker. Debian and Ubuntu trackers show which releases embed the fix; older stable branches may still carry a vulnerable version until backported.

Run‑time detection is trickier but possible. Look for sustained high CPU utilization on endpoints that process JSON, especially if the CPU spike persists as long as a particular connection or request remains active. If you suspect a ReDoS event, capture the offending input and test it in a staging environment with a patched library to confirm.

Lessons for Supply Chain Security

CVE‑2021‑42836 underscores why a small, “utility” library can become a single point of failure. GJSON has 8,500+ stars on GitHub and is used in thousands of projects, yet its vulnerable version lurked in dependency graphs for years after the fix shipped. The reasons are mundane: teams don’t bump indirect dependencies often, container images are stale, and vulnerability scanners sometimes fail to surface transitive risks.

For developers, the lesson is clear: pin exact versions, rebuild frequently, and automate drift detection. For operators and platform architects, it’s a reminder that runtime guardrails—CPU limits, network policies, admission controls—are a necessary complement to secure coding practices. No library update can protect against every future vulnerability, but defense‑in‑depth can limit the blast radius.

Vendors who embed GJSON internally pose a separate challenge. If you rely on a commercial appliance or SaaS that uses Go, ask the vendor for a security advisory. Until they release a patch, apply compensating controls at the network edge (WAF rules, input size limits) and monitor those devices for abnormal CPU patterns.

What Comes Next

The GJSON fix is a minimal, well‑scoped change that has stood the test of time. No new ReDoS vectors have been reported in the library since v1.9.3. However, any application that upgrades may encounter behavioral differences: the 10,000‑operation cap could now reject extremely complex but formerly accepted patterns. Before deploying, exercise your codebase’s standard query workload against the updated library. If you rely on deeply nested or highly elaborate pattern matches, you may need to adjust queries or raise the cap through the library’s MatchLimit configuration option (introduced alongside the fix).

Broader ReDoS risks remain endemic to string‑processing libraries across languages. This CVE is a template for how to address them: bound match complexity, audit call sites, and add regression tests. For the Windows and DevOps community, where Go‑based tooling has exploded—from Terraform providers to container runtimes—the GJSON patch is a quiet but critical piece of infrastructure hygiene. Scan your codebases today, upgrade where feasible, and build a pipeline that catches dependency risks before they become outages.