jq CVE-2026-40164: Brief Summary of Hardcoded Hash Seed Enabling Algorithmic Complexity DoS

A brief summary of CVE-2026-40164, a high severity algorithmic complexity vulnerability in jq where a hardcoded MurmurHash3 seed allows attackers to craft small JSON payloads that cause severe CPU exhaustion through hash table collisions.

CVE Analysis

7 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-04-13

jq CVE-2026-40164: Brief Summary of Hardcoded Hash Seed Enabling Algorithmic Complexity DoS
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

A roughly 100 KB JSON file can pin a jq process at 100% CPU for minutes, and a 2 MB file can stall it for hours. CVE-2026-40164 exposes this reality: every version of jq ships with a hardcoded MurmurHash3 seed that lets anyone precompute hash collisions offline, turning ordinary JSON processing into a quadratic time operation.

jq is a lightweight, zero dependency command line JSON processor written in portable C, often described as "sed for JSON." Originally created by Stephen Dolan in 2012, it has become a foundational utility across the software engineering ecosystem, embedded in CI/CD pipelines, web service backends, and data processing scripts on Linux, macOS, and Windows. Its ubiquity means this vulnerability has a broad and often invisible attack surface.

Technical Information

Root Cause: Deterministic Hashing with a Public Seed

The core issue is in src/jv.c at line 1200, where jq defines a compile time constant seed for its MurmurHash3 implementation:

static const uint32_t HASH_SEED = 0x432A9843;

This seed is used for all JSON object hash table operations. Because it is hardcoded and visible in the public source code, an adversary can replicate the exact hash function locally and brute force sets of keys that all resolve to the same hash bucket. Many modern language runtimes (Python 3.3+, Perl, Ruby, PHP) randomize their hash seeds at process startup specifically to prevent this class of attack. jq did not.

Collision Impact: O(1) to O(n²)

When a JSON object is loaded into jq, its keys are inserted into a hash table. Under normal conditions, lookups are O(1). When all keys collide into a single bucket, each lookup becomes O(n) as the implementation must walk a linear chain. Any jq expression that touches the object's keys (which is nearly all of them) then performs O(n) lookups across O(n) keys, yielding O(n²) total work.

The advisory provides concrete benchmarking data that illustrates the quadratic scaling:

Collision Key CountApproximate Payload SizeProcessing Time
1,000 keys20 KB1 second
10,000 keys200 KB100 seconds
100,000 keys2 MB3 hours

This is a textbook algorithmic complexity attack (CWE-407), compounded by the use of a reversible hash with a known seed (CWE-328). The asymmetry is striking: a 200 KB payload, trivial to transmit over any network, consumes 100 seconds of CPU time on the target.

Attack Flow

  1. Offline key generation. The attacker implements MurmurHash3 with the known seed 0x432A9843 in any language. They then enumerate candidate strings, keeping only those whose hash output matches a chosen target value. This is a purely offline computation.

  2. Payload construction. The attacker assembles a JSON object using the colliding keys. For a meaningful denial of service, 10,000 colliding keys (~200 KB) is sufficient to cause roughly 100 seconds of CPU stall per jq invocation.

  3. Delivery. The crafted JSON is submitted to any endpoint or pipeline that processes it with jq. Common vectors include:

    • API responses consumed by curl | jq patterns in CI/CD pipelines
    • JSON payloads submitted to web services that use jq for server side processing
    • Data feeds ingested by ETL scripts
  4. Impact. The jq process enters a tight CPU loop. No crash occurs; the process simply becomes unresponsive for the duration of the quadratic computation. In pipeline contexts, this can block deployments, stall monitoring, or exhaust worker pools.

Comparison to Previous jq Vulnerabilities

The advisory explicitly notes that this attack is far more practical than existing heap overflow issues in jq, which required payloads of approximately 1.43 GB. CVE-2026-40164 achieves comparable or greater disruption with a payload that is four orders of magnitude smaller.

The Fix

The commit 0c7d133c3c7e37c00b6d46b658a02244fdd3c784 replaces the static seed with a dynamically initialized random seed using system entropy. The suggested patch to src/jv.c is:

- static const uint32_t HASH_SEED = 0x432A9843; + static uint32_t hash_seed; + __attribute__((constructor)) + static void init_hash_seed(void) { + #if defined(HAVE_ARC4RANDOM) + hash_seed = arc4random(); + #elif defined(HAVE_GETENTROPY) + if (getentropy(&hash_seed, sizeof(hash_seed)) != 0) + hash_seed = (uint32_t)getpid() ^ (uint32_t)time(NULL); + #else + int fd = open("/dev/urandom", O_RDONLY); + if (fd >= 0) { read(fd, &hash_seed, 4); close(fd); } + else hash_seed = (uint32_t)getpid() ^ (uint32_t)time(NULL); + #endif + }

This ensures each jq process gets a unique seed, making offline collision precomputation infeasible.

Affected Systems and Versions

All versions of jq are affected. The advisory lists no specific version range boundary; the hardcoded seed has been present since the original implementation of the hash table in src/jv.c. No officially patched release version exists at the time of the advisory. The fix is available only via commit 0c7d133c3c7e37c00b6d46b658a02244fdd3c784 in the jqlang/jq repository.

Any deployment that passes untrusted or externally sourced JSON through jq is vulnerable. This includes but is not limited to:

  • CI/CD pipelines using curl | jq to consume external API responses
  • Web services that invoke jq for server side JSON transformation
  • Data processing and ETL scripts that ingest feeds from third party sources

Vendor Security History

The jq project, maintained by the jqlang organization on GitHub, has a history of addressing security issues in a timely manner. The jq 1.8.1 release on July 1, 2025, included fixes for multiple security vulnerabilities:

  • CVE-2025-49014: Heap use after free
  • CVE-2024-23337: Signed integer overflow

This pattern of responsive patching suggests that an official release incorporating the hash seed randomization will likely follow. Organizations should monitor the jq releases page for updates.

References

Detect & fix
what others miss

Security magnifying glass visualization