Introduction
The go.mod file in any Go project is deceptively simple — a list of module names and version pins. But each line is a trust decision. When the Trivy scanner flagged github.com/buger/jsonparser v1.1.1 in this project's dependency tree, it revealed that a single indirect dependency version pin was exposing every JSON-parsing code path to a potential Denial of Service attack.
This post walks through exactly what CVE-2026-32285 is, how the vulnerable version of buger/jsonparser could be exploited against a running Go service, and what the one-line go.mod change actually does to close the door.
The Vulnerability Explained
What is buger/jsonparser and why is it here?
github.com/buger/jsonparser is a high-performance, zero-allocation JSON parsing library for Go. It is widely used as a transitive dependency — meaning your code may not call it directly, but another library in your dependency graph does. In this project it appears as an // indirect dependency:
// go.mod (before fix)
github.com/buger/jsonparser v1.1.1 // indirect
The // indirect comment is Go's way of saying: "We don't import this ourselves, but something we depend on does." That does not mean the vulnerability is unreachable — it means the attack surface is wherever the parent dependency passes untrusted data through jsonparser.
CVE-2026-32285: Denial of Service via Malformed JSON
In buger/jsonparser v1.1.1, certain sequences of malformed or truncated JSON bytes are not handled defensively. When the parser encounters these sequences, it can:
- Panic — causing the Go runtime to crash the goroutine (or the whole process if not recovered)
- Loop or stall — consuming CPU in an uncontrolled way (CWE-400: Uncontrolled Resource Consumption)
The root cause is insufficient bounds-checking and error-path handling inside the library's byte-level parsing routines when input does not conform to expected JSON structure.
A Concrete Attack Scenario
Consider a Go service that accepts JSON payloads over HTTP — a REST API endpoint, a webhook receiver, or a message queue consumer. Internally, one of its dependencies uses buger/jsonparser to extract fields from those payloads.
An attacker sends a crafted HTTP request body:
POST /api/ingest HTTP/1.1
Content-Type: application/json
{"key": "\x00\xff\xfe
This truncated, byte-mangled payload is valid enough to pass a naive Content-Type check but malformed enough to trigger the vulnerable code path inside buger/jsonparser v1.1.1. The result: the parsing goroutine panics or stalls. With enough concurrent requests, the service becomes unavailable — a classic application-layer DoS.
Because buger/jsonparser is an indirect dependency, developers often don't realize their service is exposed until a scanner like Trivy surfaces it.
The Fix
The fix is surgical and low-risk: bump github.com/buger/jsonparser from v1.1.1 to v1.1.2 in both go.mod and go.sum.
go.mod Change
- github.com/buger/jsonparser v1.1.1 // indirect
+ github.com/buger/jsonparser v1.1.2 // indirect
v1.1.2 patches the malformed-input handling so that the parser returns a proper error instead of panicking or looping. Valid JSON inputs are completely unaffected — the change only tightens behavior on the invalid-input path.
go.sum Change
+ github.com/buger/jsonparser v1.1.2 h1:frqHqw7otoVbk5M8LlE/L7HTnIq2v9RX6EJ48i9AxJk=
+ github.com/buger/jsonparser v1.1.2/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
The go.sum file stores cryptographic hashes (SHA-256) of every module version that enters the build. Adding the v1.1.2 hashes here is mandatory: Go's module system will refuse to use a version whose hash is not recorded in go.sum, preventing supply-chain tampering. The old v1.1.1 entries remain in go.sum for historical auditability but are no longer selected by the build.
Why Two Files?
| File | Role | What Changed |
|---|---|---|
go.mod |
Declares the minimum required version | Version pin updated from v1.1.1 → v1.1.2 |
go.sum |
Cryptographic integrity ledger | Hash entries for v1.1.2 appended |
Both changes are required. Updating only go.mod without go.sum would cause go build to fail with a checksum mismatch error.
Prevention & Best Practices
1. Run govulncheck in CI
Go's official vulnerability checker scans your module graph against the Go Vulnerability Database:
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...
Unlike Trivy, govulncheck performs call-graph analysis and can distinguish between a vulnerable symbol that is actually reachable versus one that is pulled in but never called.
2. Add Trivy or Snyk to Your Pipeline
# Example GitHub Actions step
- name: Scan dependencies
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
exit-code: '1'
severity: 'HIGH,CRITICAL'
This catches CVEs in go.mod before they reach production.
3. Set go.mod Minimum Version Constraints Deliberately
When you pin an indirect dependency, prefer the latest patched minor version rather than the version your dependency manager first resolves to:
go get github.com/buger/jsonparser@v1.1.2
go mod tidy
4. Size-Limit and Pre-Validate Incoming JSON
Even with a patched library, defense in depth matters. Reject payloads that exceed a reasonable size before they reach any parser:
http.MaxBytesReader(w, r.Body, 1<<20) // 1 MB limit
5. Relevant Standards
- CWE-400: Uncontrolled Resource Consumption — https://cwe.mitre.org/data/definitions/400.html
- CWE-20: Improper Input Validation — https://cwe.mitre.org/data/definitions/20.html
- OWASP: Denial of Service Cheat Sheet — https://cheatsheetseries.owasp.org/cheatsheets/Denial_of_Service_Cheat_Sheet.html
Key Takeaways
- Indirect Go dependencies carry real CVE risk. The
// indirectlabel ingo.moddoes not mean "safe to ignore" — it means your attack surface includes code you didn't write and may not have reviewed. go.sumis a security control, not just bookkeeping. The hash entries forv1.1.2ensure the exact patched bytes are used at build time; never skip updatinggo.sumwhen changinggo.mod.- Malformed JSON DoS is a realistic threat for any HTTP-facing Go service. If your service accepts JSON from untrusted clients, the parsing library version matters as much as your own input-validation logic.
govulncheckcan tell you if the vulnerable symbol is actually reachable, saving triage time when you have many flagged indirect dependencies.- A one-line version bump in
go.modclosed a critical availability gap — the cost of the fix was near zero; the cost of ignoring it could have been a production outage.
How Orbis AppSec Detected This
- Source: Any HTTP endpoint or message consumer in the application that accepts untrusted JSON payloads and routes them through a dependency that calls
buger/jsonparser. - Sink: The byte-parsing routines inside
github.com/buger/jsonparser v1.1.1that process raw JSON bytes without adequate bounds-checking on malformed input sequences. - Missing control: No version constraint in
go.modrequired the patchedv1.1.2release; the project was locked to the vulnerablev1.1.1. - CWE: CWE-400 — Uncontrolled Resource Consumption.
- Fix: Updated
go.modto requiregithub.com/buger/jsonparser v1.1.2and added the corresponding cryptographic checksums togo.sum.
Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.
Conclusion
CVE-2026-32285 is a textbook example of why dependency hygiene is a security practice, not just a maintenance chore. The vulnerable code wasn't written by the application team — it lived two layers deep in the dependency graph — but it was fully capable of taking down the service. The fix required changing exactly one version string in go.mod and adding two lines to go.sum. That's a remarkably low cost for closing an availability risk that could have manifested as a production incident.
The broader lesson: treat every line in go.mod as a security decision. Automate scanning, enforce version floors in CI, and don't let // indirect lull you into a false sense of safety.