GJSON ReDoS CVE-2021-42836: Patch to v1.9.3 Stop CPU DoS

  • Thread Author
GJSON versions before 1.9.3 contain a Regular Expression Denial of Service (ReDoS) flaw — tracked as CVE-2021-42836 — that can be triggered by crafted JSON paths or queries and allow an attacker to drive CPU consumption to the point of service disruption.

Neon circuit-drawn dashboard in a server room showing JSON paths, CPU usage, and CVE-2021-42836.Background / Overview​

GJSON is a widely used Go library that provides fast, path-style access to values inside JSON documents. Its convenience and speed have made it a common dependency in cloud services, command-line tools, agents, and system utilities that accept JSON input. In October 2021, researchers and users reported that certain query and pattern-matching code paths in GJSON could be driven into excessively expensive regular-expression matches by carefully constructed input, producing a ReDoS condition. The problem was cataloged as CVE-2021-42836 and given a high severity rating (CVSS 3.x base score 7.5).
This article summarizes what happened, explains the technical cause, analyzes the real-world risk for applications and the software supply chain, and gives concrete mitigation and remediation steps for developers, maintainers, and operators who rely on GJSON.

The vulnerability in short​

  • A ReDoS (regular expression denial of service) weakness allows CPU/time exhaustion when GJSON processes certain queries or pattern matches.
  • The bug affects all releases of GJSON prior to v1.9.3; v1.9.3 contains the fix.
  • The root cause is uncontrolled complexity when performing pattern matches used by the library’s query and “like” operators; the library originally delegated to a match routine without limits, which allowed pathological patterns to cause catastrophic backtracking.

Why this matters: availability, supply chain, and exposure​

Regular-expression-based DoS is a practical attack vector in networked services and local tooling alike. When an attacker can supply JSON that flows into GJSON (via an API, message bus, log parser, agent input, or CLI), they can cause the process using GJSON to burn CPU, slow to a crawl, or become effectively unavailable to legitimate users until the offending input is removed or the process is restarted.
  • The National Vulnerability Database and other vulnerability trackers classify CVE-2021-42836 as an Uncontrolled Resource Consumption issue (CWE‑400) with high availability impact.
  • Downstream Linux distributions and vendors packaged the vulnerable versions; Debian and Ubuntu trackers list packages that may remain vulnerable until rebuilt or upgraded in their repositories. That means many deployed systems — especially older images or unmaintained containers — can still carry this risk.
  • ReDoS is attractive for attackers because exploitation usually requires no privileges and no interaction beyond sending crafted input; complexity-based regex failures are both silent (no crash) and inexpensive for an attacker to generate while being expensive for the victim to process.
Because GJSON is a library, the real operational exposure depends on how an application consumes JSON and whether user-controllable paths are passed to its pattern-matching features. But in services that parse untrusted JSON and use GJSON queries, the vulnerability translates into a credible denial-of-service vector.

Technical analysis: where the code went wrong​

The vulnerable code paths​

The GJSON code used a match routine (provided by a companion package) to evaluate pattern matches both when:
  • Matching object keys during parsing, and
  • Evaluating query operators that match a string value against a pattern (for example, the "%" operator used in GJSON query syntax). (github.com)
In the vulnerable versions, the library invoked the unrestricted match function directly. That function — when given certain complex patterns — could take exponential time because of backtracking in the regular-expression engine, which allowed crafted inputs to consume unbounded CPU cycles.

Proof and example​

The original GitHub issue that reported the problem included a minimal reproduction: a specially constructed JSON and a path string that, when fed to gjson.Get(...), triggers the expensive matching behavior. The sample payload demonstrated the path-style query and the type of input patterns that cause the engine to spin — and it was sufficient for maintainers to reproduce and verify the symptom. (github.com)
(As typical with ReDoS cases, the exploit is not a simple textual "one-liner" regex but a combination of query operator usage and JSON content that together drive the match routine into pathological backtracking.)

The fix: limit the match complexity​

The maintainer’s fix shipped in the code commit that implements a safety wrapper: rather than calling the unconstrained match function, the library now uses a matchLimit wrapper that enforces an operation cap (10,000 match operations in the fix) via the MatchLimit API. This brakes runaway matching, bounding CPU cost for any single match operation and effectively nullifying the ReDoS vector. The commit changed call sites in parseObject and queryMatches to replace direct calls to match.Match(...) with calls to matchLimit(...), and it added test cases covering the issue. (github.com)
That patch is included in the v1.9.3 release of GJSON. Applications that upgrade to v1.9.3 or later receive the match-limit protection.

Confirmed scope and references​

  • The NVD entry for CVE-2021-42836 explicitly states: “GJSON before 1.9.3 allows a ReDoS (regular expression denial of service) attack.” and lists the vulnerability as Uncontrolled Resource Consumption.
  • The maintainers made the targeted change (use of MatchLimit, 10,000 op cap) in a public commit that is tied to the v1.9.3 fix. The commit message describes the intent to “limit the complexity of 'like' queries that match on a pattern”. (github.com)
  • OSV and other vulnerability databases link the CVE to the repo commit and to the GO advisory entry; additional vulnerability pages (Ubuntu, Debian trackers) mark package versions that remain vulnerable until upgraded.
These independent confirmations — NVD, the upstream commit, and multiple distro trackers — provide cross-verification that the vulnerability exists in pre‑1.9.3 releases and that v1.9.3 contains the intended remediation.

Operational risk: what an attacker can and cannot do​

  • What an attacker can do:
  • Submit crafted JSON input that triggers expensive matches and consumes CPU, slowing or stalling the process. Because GJSON is used in many server-side contexts, this can translate to service degradation or full unavailability for clients.
  • Execute repeated, low-cost remote attempts that cumulatively exhaust host resources (e.g., many concurrent expensive matches), especially if the application processes each input synchronously.
  • What an attacker cannot do (based on the available reports):
  • The vulnerability is not a code-execution or direct data-exfiltration flaw. Its primary impact is on availability (DoS). NVD and distributors classify confidentiality and integrity impact as nil or none.
  • Real-world constraints:
  • The exploit requires the attacker to supply JSON or query data that reaches the vulnerable match code. If an application strictly controls or sanitizes query expressions and does not expose pattern operators to untrusted input, the attack surface is reduced.
  • Hosted or multi-tenant environments that allow users to upload JSON-processing jobs or arbitrary queries are particularly at risk.

Detection, scanning, and inventory — how to find affected systems​

  • Inventory code and dependencies:
  • For Go projects, list module dependencies to find whether they use github.com/tidwall/gjson. Use the module graph (go list -m all) and scan for the tidwall/gjson module name.
  • Scanners and databases:
  • Run language-specific vulnerability checks such as OSV/packaged vulnerability tools or govulncheck (for Go) to detect usages of the vulnerable version. Public vulnerability feeds (NVD, OSV) include the CVE and map it to the package and fixed version.
  • Distribution packages:
  • Check your system packages for golang-github-tidwall-gjson and compare versions against the distribution trackers (Debian/Ubuntu) to determine whether the packaged library needs a vendor update.
  • Runtime indicators:
  • High CPU spikes correlated with particular JSON-processing endpoints or inputs are a behavioral indicator. If possible, capture input samples that cause the spike and test them in a controlled environment to confirm whether GJSON matching is involved.

Mitigations and workarounds (short-term and long-term)​

If you discover vulnerable code in your stack, here are prioritized actions:
  • Primary (recommended): Upgrade GJSON to v1.9.3 or later in every project and container image that uses it. The upstream fix enforces a match complexity cap. (github.com)
  • If you cannot immediately upgrade:
  • Disallow or sanitize untrusted pattern expressions. Prevent users from supplying query strings or operators that end up passed verbatim into the library’s pattern-match API.
  • Move JSON parsing and matching into a separate worker process or sandbox with CPU and time limits (cgroups, short-lived containers, or OS-level CPU/memory constraints) so that a busy loop caused by a ReDoS input cannot take down the whole service.
  • Apply input-rate limits and request throttling on the API endpoints that accept JSON or text queries to reduce the ability of a remote attacker to flood the service with pathological inputs.
  • Use an application-level timeout for expensive operations and return an error if pattern evaluation exceeds a safe budget.
  • For packagers and distro maintainers:
  • Rebuild packages against a fixed upstream release (v1.9.3+) and produce security updates for consumers. Distributors that track the golang module packaging must ensure packages are rebuilt to bring in the matchLimit change.

Remediation checklist (practical steps)​

  • Identify all projects (apps, agents, helper tools) that import github.com/tidwall/gjson.
  • For each project:
  • Update the module requirement to v1.9.3 or newer:
  • Example: go get github.com/tidwall/gjson@v1.9.3
  • Run go mod tidy and rebuild artifacts.
  • Re-run unit and integration tests, paying attention to any custom behavior around pattern matching and query operators.
  • Rebuild and redeploy containers and packages that include the updated binary or libraries.
  • If you cannot upgrade immediately, apply the mitigations described (sanitize inputs, rate-limiting, sandboxing).
  • Add a dependency-monitoring rule so future vulnerable versions are flagged when they appear in the dependency graph (SCA tools, CI checks).
  • For third-party or vendor software that uses GJSON internally, request a vendor advisory and timeline to update; consider temporary compensating controls (WAF, input filtering) if vendor updates are delayed.

How to test that the fix works​

  • Reproduce the original issue in a safe lab by using the minimal example published in the upstream issue. The original issue included a test string that caused the expensive behavior; test this against a binary built with the updated module and verify that the operation is bounded and returns quickly. (github.com)
  • Monitor CPU/time for pattern operations and compare behavior before and after the upgrade.
  • Ensure test coverage includes fuzzing or unit tests that assert complex paths do not cause runaway CPU usage. The maintainers added tests that exercise the patched code paths. (github.com)

Supply-chain implications and disclosure timeline​

  • The CVE was disclosed in October 2021 and mapped across CVE/NVD, OSV, GitHub issues, and distro trackers. Upstream responded with a commit that enforces complexity limits and then released the patched version, v1.9.3.
  • Because GJSON is a small-but-common library, the typical risk comes from its use inside other projects rather than direct exposure from the library itself. This makes supply-chain hygiene (dependency scanning, rebuilds, pinned versions) the primary long-term defense. Distribution package maintainers and container image creators should ensure they propagate the fix into downstream binaries and images. Debian and Ubuntu trackers indicate varying package statuses, so administrators should verify package versions in their environments and apply distribution updates where available.

Strengths of the upstream remediation, and remaining risks​

Strengths​

  • The upstream fix is targeted and minimal: it replaces unbounded calls with a MatchLimit wrapper and sets an explicit operation cap. That is a low-risk change that preserves functionality while enforcing a safety bound. (github.com)
  • The patch is verifiable and covered with test additions; maintainers committed the change and documented the rationale clearly in the commit message. (github.com)
  • The vulnerability is well-tracked across NVD/OSV and distribution trackers, enabling automated detection once tools ingest the advisories.

Remaining risks and caveats​

  • The fix imposes an operation cap (10,000 operations in the commit). An operation cap is a pragmatic guard but introduces an implicit behavior change: extremely large but legitimate patterns could be limited or rejected. Applications that were relying on extremely complex matches may notice changed behavior and should validate expected outcomes after upgrading. (github.com)
  • The presence of GJSON in the dependency graph is not enough to determine exposure; whether the vulnerable code is reachable depends on how the application uses the library. False negatives can occur in static scanning if SCA tools don’t report runtime invocation characteristics. Use both static dependency scanning and runtime/behavioral monitoring.
  • Some packaged distributions may ship a backported or older version of the library; administrators should treat distribution package versions as authoritative for host risk and not assume every container or binary has been rebuilt with upstream fixes.

Practical recommendations for different audiences​

For application developers​

  • Upgrade to github.com/tidwall/gjson v1.9.3 or later as a first step. Rebuild and redeploy quickly.
  • Add unit tests that include pathological patterns (from the original issue) to ensure the app gracefully bounds processing time.
  • Avoid exposing pattern or query operators directly to untrusted users where possible; prefer fixed queries, whitelists, or an allowlist of safe patterns.
  • Add SCA checks to CI that flag versions < v1.9.3.

For ops, SRE, and security teams​

  • Inventory services and containers for the vulnerable module; prioritize public-facing endpoints and multi-tenant services where exploit impact is highest.
  • If immediate patching is impossible, implement rate limiting, request filtering, and sandboxing to reduce attack surface.
  • Monitor CPU usage and set alerts for sudden spikes in JSON-processing endpoints; capture offending inputs for analysis.

For packagers and downstream maintainers​

  • Rebuild and publish patched packages that include GJSON v1.9.3+. Communicate the update to downstream consumers and ensure update channels (e.g., apt repositories, container registries) are refreshed.
  • Where backports are required, test for behavioral differences introduced by the match limit and document them.

Final assessment and conclusion​

CVE-2021-42836 is a clear, well-documented instance of a classic ReDoS problem in a widely used parsing/query library. The vulnerability’s impact is real: an attacker who can provide JSON or query input to an application using a vulnerable GJSON version can cause resource exhaustion and denial of service. The fix that landed in v1.9.3 is appropriate and pragmatic: it bounds match complexity rather than attempting to eliminate pattern-based functionality.
From an operational point of view the immediate steps are simple and urgent: inventory your code and systems, update to GJSON v1.9.3 or later, rebuild artifacts and containers, and apply runtime mitigations where immediate updates are not feasible. From a strategic perspective, this CVE is a fresh reminder that small third‑party libraries are a meaningful part of your attack surface; supply‑chain controls, dependency scanning, and runtime limits are essential practices for resilient systems.
If you maintain or operate services that accept untrusted JSON and use GJSON for path queries, treat this as a high-priority remedial item: upgrade, test, and deploy the fix — and add ReDoS inputs to your regression suite so this class of problem does not reappear silently.

Source: MSRC Security Update Guide - Microsoft Security Response Center
 

Back
Top