The Go project has released versions 1.17.12 and 1.18.4 to patch a denial-of-service vulnerability in the standard library’s gzip reader. Tracked as CVE-2022-30631, the flaw lets an attacker crash a Go program by sending a tiny, malformed archive that triggers uncontrolled recursion—exhausting the process stack until the application panics.
If a service running on Windows, Linux, or any other platform decompresses user-supplied gzip data using an affected Go runtime, that service is at risk. The fix replaces the recursive logic in compress/gzip.Reader.Read with a simple iterative loop, removing the stack growth and the attack surface entirely.
What the vulnerability lets an attacker do
At the core of the bug is how Go’s gzip reader handles concatenated gzip members. The gzip format allows multiple compressed streams to be chained together in a single file; a decompressor is expected to process each member sequentially and output the combined decompressed data.
In the vulnerable implementation, the Reader.Read method used recursion to advance from one member to the next. For normal archives—which contain just one or two members—this recursion is harmless. But an attacker can craft an archive with thousands (or millions) of zero‑length compressed members. Each empty member still forces the reader through the member‑end transition code path, and each transition added a new stack frame.
With enough concatenated empty members, the recursion depth grows until the Go runtime runs out of goroutine stack space and panics. The process crashes, and any service depending on it becomes unavailable. The exploit requires no authentication, no special privileges, and can be delivered through any channel that accepts gzip‑encoded input: HTTP file uploads, API payloads, email attachments, or even automated batch jobs.
Because zero‑length members add only a few bytes to the archive (a minimal gzip header), the attack payload is extremely small—often less than a kilobyte per thousand members. This makes it easy to embed in network traffic and difficult to detect with simple size‑based filters. The vulnerability has been assigned CWE‑674 (Uncontrolled Recursion) and carries a CVSS v3.1 base score of 7.5 (High), primarily for its availability impact.
Who’s at risk—Windows and beyond
The bug lives inside the Go standard library itself. That means any application built with a vulnerable Go version and that decompresses gzip streams is potentially affected, regardless of the operating system. On Windows, that includes:
- Self‑hosted Go services running directly on Windows Server or Windows desktop.
- Windows‑based CI/CD runners that process build artifacts or test fixtures.
- Containerized Go applications running on Windows container hosts, whether in Docker, Kubernetes, or Azure environments.
- Desktop tools and utilities that open compressed archives (many Go‑based CLI tools ship with built‑in decompression).
Even if you are not a developer, you might be using a popular tool written in Go—such as Docker CLI components, Terraform, or Kubernetes utilities—that could be statically linked with the vulnerable compress/gzip code. If the upstream vendor has not yet rebuilt their binaries with a patched Go version, you remain exposed.
Dev shops that vendor the Go standard library (copying its source directly into their own repository) face an additional hazard: updating the Go toolchain on the build machine does not automatically update vendored code. Only a rebuild after updating the vendored copy removes the vulnerability.
How we got here: discovery and a swift fix
The issue was reported through the Go project’s security tracker (GO-2022-0524) and publicly disclosed on July 20, 2022. The Go security team acknowledged the problem in compress/gzip and traced it to the recursive member‑reading logic. A patch was merged into the release branches that same day, converting the recursion into a simple for loop.
The fix is contained in commit b2b8872c. The commit message is blunt: “Replace recursion with iteration in Reader.Read to avoid stack exhaustion.” With that change, the gzip reader no longer grows the stack per member; it reuses the same frame, making the attack impossible.
Google released Go 1.17.12 and Go 1.18.4 on July 12, 2022, with the fix included. All later Go versions also contain the patch. The rapid turnaround—less than two months from report to release—demonstrates the maturity of the Go project’s vulnerability handling. At the same time, major Linux distributions (Ubuntu, Debian, SUSE, Amazon Linux, Red Hat) and cloud providers soon packaged updates for their Go‑based components, and third‑party vendors such as IBM published advisories for affected storage and data‑processing products.
What you must do now
The patch is straightforward to apply, but the operational follow‑through requires a methodical approach, especially on Windows where Go is often installed from the official binary distributions rather than a system package manager.
1. Upgrade the Go toolchain
If you build Go applications in‑house, update the Go SDK on every development machine, CI agent, and build server:
- For Go 1.17 users: install Go 1.17.12 or later.
- For Go 1.18 users: install Go 1.18.4 or later.
- For newer projects, use the latest stable release (which already contains the fix).
Download the Windows MSI installer or ZIP archive from golang.org/dl. If you use Chocolatey, choco upgrade golang will fetch the latest patched version.
2. Rebuild and redeploy all affected binaries
Simply updating the SDK is not enough. You must rebuild every binary that uses compress/gzip—and re‑deploy it into production. This step is critical for statically linked Go executables because the vulnerable library code is baked into the binary itself.
- Identify all repositories that import
compress/gzipdirectly or transitively. - Perform a clean build with the updated Go version.
- In containerised environments, rebuild your Docker images with a base image that uses a fixed Go runtime or a multi‑stage build that uses the patched SDK.
3. Audit for vendored copies
Many Go projects copy (vendor) the standard library into their own source tree to achieve reproducible builds. If you vendor compress/gzip, you must update the vendored source and commit the change before rebuilding. A simple go mod vendor after upgrading the toolchain will refresh the vendor directory, but you may also need to pin to the exact fixed revision. Run govulncheck or a static analysis tool to confirm the vulnerability is absent.
4. Check third‑party dependencies
Your application may link against a library that itself calls compress/gzip. Search your dependency tree for any package that deals with gzip decompression. Tools like go list -deps and vulnerability scanners (e.g., Snyk, Trivy, or GitHub’s Dependabot) can flag CVE-2022-30631 in your module graph. Once identified, validate that the dependency has been rebuilt with the patched Go version, or ask the vendor for an update.
5. Apply OS‑level updates (if you use packaged Go)
While Windows does not ship a system‑wide Go package, some enterprise environments install Go via third‑party software distribution platforms or custom MSI packages. Ensure those packages are updated. For Linux VMs or WSL2 instances running Go, apply the distribution’s security updates immediately.
6. Harden decompression paths—whether you can patch or not
Even after patching, treat any incoming gzip stream as untrusted. Add defensive layers:
- Isolate decompression in a dedicated worker process or container with tight memory and CPU limits. A crash there won’t take down the main application.
- Set timeouts on decompression operations. The standard
timepackage can wrap anio.Readerto abort if reading takes too long. - Limit input size before decompression. Reject archives over a few megabytes or scan the header count to detect suspiciously high member counts.
- Use
MaxBytesReaderor similar to cap the amount of data read from the decompressed stream.
If you are unable to patch immediately—perhaps because a critical binary cannot be rebuilt right away—these controls become your primary defense. While they do not eliminate the underlying bug, they reduce the likelihood of a successful denial‑of‑service.
The bigger lesson: recursion is a liability in parsers
CVE-2022-30631 is a textbook example of why language and library designers increasingly avoid recursion when processing untrusted input. Every frame on the call stack is a resource that an attacker can try to exhaust. The fix—replacing recursion with iteration—is a pattern worth adopting across all input‑parsing code.
For Go developers, the episode also underlines a core operational reality: vendoring reduces update agility. When a security flaw is patched in the standard library, every vendored copy becomes a time bomb unless explicitly refreshed. Teams that vendor need to establish a policy for regularly synchronizing with upstream security fixes and rebuilding affected components.
What to watch next
The fix eliminates the specific recursion bug, but the broader class of decompression‑bomb and resource‑exhaustion attacks remains. Expect to see more fuzzing‑driven finds in compression libraries across all languages. Microsoft, for example, has invested heavily in fuzzing the Go standard library through its Microsoft Security Response Center, and the Go project itself continuously runs oss‑fuzz on critical packages.
If you operate a service that accepts compressed uploads, make it a habit to review your decompression pipeline for bottlenecks, recursion, and unbounded memory usage. The next vulnerability might not be in gzip—but the defense‑in‑depth you put in place today will blunt whatever comes.
The bottom line: update your Go toolchain, rebuild your binaries, and treat every decompression call as a potential attack surface. The patch is small, the payoff is large.