A simple, malformed gzip archive can still bring down a Go-based service: an uncontrolled recursion bug in Go’s standard library compress/gzip Reader.Read lets an attacker crash applications by exhausting the stack when parsing archives composed of many concatenated zero-length compressed files. (go.dev)
On July 20, 2022, a vulnerability was disclosed and tracked as CVE‑2022‑30631 (Go tracker ID GO‑2022‑0524). It affects the Go standard library’s compress/gzip package: specifically, the Reader.Read implementation used to read gzip streams. The underlying defect is uncontrolled recursion — a logic path that uses recursion to advance through concatenated gzip members will recurse for each empty member in the archive. An archive purposely constructed with a very large number of concatenated zero‑length compressed members causes the recursion depth to grow until the process stack is exhausted and the program panics. This is a denial‑of‑service (DoS) condition that impacts availability only; it does not by itself enable code execution or data disclosure.
The Go project fixed the issue by changing the Reader.Read implementation to use iteration rather than recursion, and the fix was merged as a small patch in May–July 2022. The correction was included in the Go releases 1.17.12 and 1.18.4; users of earlier versions should consider those releases the minimum safe versions. The upstream code change and commit message are explicit about replacing recursion with iteration to avoid stack exhaustion. (go.googlesource.com)
However, the practical exploitation surface varies:
Because the change is localized and relatively small, it was straightforward to backport into supported release branches and into vendor packaging, which is why the fix appears in 1.17.12 and 1.18.4 and then in later releases.
A few lessons emerge:
Key takeaways:
Conclusion
CVE‑2022‑30631 underscores that even widely used standard libraries can harbor availability‑only vulnerabilities with outsized operational impact. The fix is available and straightforward — replace recursion with iteration in the gzip reader — but full remediation requires a disciplined program: inventory, patch, rebuild, and isolate. Operators who treat decompression as a privileged operation (sandboxing, limits, and dedicated workers) will be far more resilient than those who do not. Apply the Go security releases, update vendor packages, and harden decompression paths to remove this attack surface from your critical services. (go.googlesource.com)
Source: MSRC Security Update Guide - Microsoft Security Response Center
Background / Overview
On July 20, 2022, a vulnerability was disclosed and tracked as CVE‑2022‑30631 (Go tracker ID GO‑2022‑0524). It affects the Go standard library’s compress/gzip package: specifically, the Reader.Read implementation used to read gzip streams. The underlying defect is uncontrolled recursion — a logic path that uses recursion to advance through concatenated gzip members will recurse for each empty member in the archive. An archive purposely constructed with a very large number of concatenated zero‑length compressed members causes the recursion depth to grow until the process stack is exhausted and the program panics. This is a denial‑of‑service (DoS) condition that impacts availability only; it does not by itself enable code execution or data disclosure.The Go project fixed the issue by changing the Reader.Read implementation to use iteration rather than recursion, and the fix was merged as a small patch in May–July 2022. The correction was included in the Go releases 1.17.12 and 1.18.4; users of earlier versions should consider those releases the minimum safe versions. The upstream code change and commit message are explicit about replacing recursion with iteration to avoid stack exhaustion. (go.googlesource.com)
What exactly goes wrong (technical details)
How gzip streams are structured
A gzip file can be made of one or more concatenated gzip members; decompressors are expected to read successive gzip members and present the concatenation of their decompressed payloads. In legitimate archives, concatenated members are rare; however, the specification allows them.The bug: recursion per member
In affected Go versions prior to the fixes, the compress/gzip Reader.Read implementation contained an internal code path that recursed when it encountered the end of a gzip member and needed to continue reading the next member. That recursion was safe for normal inputs, but if a file contained an extreme number of members — particularly 0‑length compressed members that advance processing but produce no output — the code would recurse one level per member. With enough members, the call stack grows until the process runs out of stack space, triggering a runtime panic in Go (which typically crashes the goroutine or the process if unhandled). This is classed as CWE‑674: uncontrolled recursion in many vulnerability databases. (go.dev)Why 0‑length members matter
Zero‑length members are cheap to produce and cheap to check for, but each member still causes the Reader to transition through the member‑end handling code path. Because each such transition added a recursion frame in the vulnerable implementation, an attacker can craft a small file (many tiny gzip headers with no payload) that nevertheless causes deep recursion. That makes the attack bandwidth‑efficient and easy to embed in network protocols or uploaded artifacts that an application may accept and process. Multiple independent technical writeups, distro advisories and the Go project itself point to this exact mechanism.Affected versions and scope
- Vulnerable: Go versions before 1.17.12, and Go versions >= 1.18.0 and before 1.18.4. In short: any build that includes the old recursive Reader.Read code.
- Fixed in: Go 1.17.12 and Go 1.18.4 (and all later releases). The fix replaced recursion with iteration in Reader.Read. (go.googlesource.com)
- Common downstream impact: many server applications, CLIs, CI tools, containers, and platform components that embed Go (including vendor‑packaged Go runtimes and tools) may inherit the vulnerability if they use an affected Go version or ship a vendored compress/gzip implementation. Linux distributions and cloud vendors subsequently shipped fixes or backported patches into their packages; consult the distro advisory for your platform.
Severity, exploitability, and real‑world risk
Security trackers uniformly classify CVE‑2022‑30631 as a high‑availability impact bug (CVSS v3.1 base score ~7.5 in many databases). The core risk is denial of service by crashing or panicking a process that reads an attacker‑controlled gzip stream. The vector is network‑accessible in many real use cases (for example, an HTTP server that accepts file uploads or processes user‑supplied archives). Attack complexity is low: no authentication or user interaction is required in many scenarios.However, the practical exploitation surface varies:
- Services that treat uploaded archives as untrusted input and decompress them in the main process without timeouts or resource limits are at highest risk.
- Many applications process files in separate worker processes, with limits and sandboxing; those setups significantly reduce the blast radius.
- In some environments the Go runtime or environment's stack limits make the attack easier or harder; the exploit depends on reaching recursion depth sufficient to exhaust the runtime goroutine or thread stack. Because stack sizes vary by platform and runtime configuration, exact number of members required will differ. Distributors and cloud providers judged the flaw important enough to push fixes.
How it was fixed (what changed)
The Go team’s patch replaces the recursive logic with an iterative loop: instead of making a new stack frame for each subsequent concatenated member, the Reader now advances to the next member using iteration and controlled state transitions. That change removes the linear growth of stack frames for pathological inputs and prevents the stack exhaustion attack vector. The commit message is explicit: "Replace recursion with iteration in Reader.Read to avoid stack exhaustion" and cites the CVE and the internal issue. (go.googlesource.com)Because the change is localized and relatively small, it was straightforward to backport into supported release branches and into vendor packaging, which is why the fix appears in 1.17.12 and 1.18.4 and then in later releases.
Detection, mitigation, and remediation guidance
If you are responsible for any Go‑based service or an application that unpacks gzip streams, treat the vulnerability as actionable. Use the following checklist.Immediate remediation (what to do now)
- Upgrade the Go runtime used to build your binaries:
- For Go 1.17 users: upgrade to 1.17.12 or later.
- For Go 1.18 users: upgrade to 1.18.4 or later.
- For all other channels, use the most recent stable release. (go.googlesource.com)
- If you use distribution packages or vendor‑packaged Go, install the vendor/distro security updates that reference CVE‑2022‑30631 (Amazon Linux, Ubuntu, Debian, SUSE, Red Hat, etc.). Many distros published advisories and backports; check your distro’s security tracker and apply the updates.
- If you cannot upgrade immediately, consider temporary mitigations:
- Isolate decompression: perform untrusted gzip decompression in a dedicated worker process or container with tight resource limits (CPU, memory, stack), so an exploited worker can be terminated without taking down the main service.
- Enforce timeouts and file size limits: restrict how long decompression may run and cap the total bytes or member count you will process.
- Reject suspicious inputs: if you can detect an unusually high number of gzip headers or very short member payloads, reject or quarantine the input for offline inspection.
- Use alternative libraries only if you have vetted them for similar issues; replacing one standard library with another third‑party library is not guaranteed safer without review.
- Audit third‑party products and containers: many commercial and open‑source products bundle Go or ship binaries built with Go. Check vendor advisories for mentions of CVE‑2022‑30631 and apply any vendor patches. Examples of vendors that published bulletins include cloud providers and storage vendors; follow your vendor’s guidance.
Detection and monitoring
- Look for sudden panics or crash loops in processes that handle archives. Enable robust logging around file‑upload and decompression code paths.
- Monitor for elevated rates of failed decompression or unusual HTTP requests that contain many short gzip members. Rate‑limit endpoints that accept file uploads.
- If possible, run the application under a fuzzer or input‑sanitizing harness in a staging environment to detect resubmissions of malformed gzip content. Note: run any tests in isolated labs. (go.dev)
Why this class of bug matters (bigger picture)
Uncontrolled recursion vulnerabilities are deceptively simple but potent. They exploit a language or library’s handling of nested or concatenated structures — common in compression, parsing, or recursive data formats — to grow resource usage linearly with malicious input. In modern microservice and cloud architectures where services frequently decompress data received from clients, a single vulnerable library can become an attack vector across many products and deployments.A few lessons emerge:
- Standard libraries must be treated like any other dependency for security maintenance. Even core language libraries can contain subtle logic issues that become high‑risk when used at scale.
- Vendoring and static linking, practices common in Go, change how quickly a fix can reach production. If a product vendors older stdlib code into its repository, simply upgrading the system Go runtime is insufficient — the vendored code must be updated and the product rebuilt. This is a common root cause for delayed remediation.
Practical, prioritized actions for operators anpers (short term)
- Rebuild and redeploy critical services with Go >= 1.17.12 or >= 1.18.4.
- Where rebuilding is not immediately possible, implement process isolation for decompression and apply input size/time limits.
- Review any vendored copies of stdlib packages in your source trees and update them; don’t assume that updating the machine Go toolchain fixes embedded code. (go.googlesource.com)
- Ops / platform teams
- Patch host packages that ship Go or Go‑built binaries via your OS vendor. Distros published CVEs and updates — apply them in your patching windows.
- Add monitoring rules for decompression failures and rapid restarts; automate rollbacks or quarantines when worker processes panic repeatedly.
- Security teams
- Add CVE‑2022‑30631 to your inventory and scanning rules (SCA/fuzzing pipelines, SBOM checks). Use CVE identifiers and CVE‑to‑component mappings to find affected images.
- If you rely on third‑party SaaS or managed services, ask vendors whether their stacks were rebuilt or patched for this CVE and what mitigation controls (sandboxing, resource limits) are in place. Note that vendor attestations vary; the Microsoft Security Response Center is one example of an authoritative advisory channel that vendors and customers use for disclosure context.
For incident responders: triage checklist
- Confirm whether the affected process uses a vulnerable Go runtime or ships a vendored compress/gzip implementation.
- If a process has panicked repeatedly, inspect the stack traces and logs; panic traces often show the library function (compress/gzip.Reader.Read) in the trace.
- Replace or patch the binary immediately: rebuild with Go 1.17.12 / 1.18.4 or apply vendor patches, then redeploy under controlled release gates.
- If immediate update is impossible, rate‑limit and isolate the functionality that performs decompression, and consider temporarily disabling automatic processing of user‑supplied archives.
- Record indicators of compromise: IPs or request patterns that attempted the malformed archives and add them to network/ingress defenses if appropriate.
Case studies and downstream impact
Several distribution vendors and product vendors referenced CVE‑2022‑30631 in their advisories. Amazon Linux, Ubuntu, Debian and SUSE published entries mapping the CVE to their Go packages and to downstream components that include the library. Vendors such as IBM called out embedded uses in storage systems and Ceph components that rely on Go, urging customers to upgrade. This is a typical downstream effect for language runtime vulnerabilities: the ecosystem must coordinate updates across OS packages, container images, and vendor products to reach full remediation.Strengths in how the issue was handled — and lingering risks
Strengths:- The Go team produced a small, targeted fix that eliminated the root cause by switching to iteration instead of recursion. The fix was committed, reviewed and released across supported branches quickly, which is the expected response model for language maintainers. (go.googlesource.com)
- Major distributions and cloud vendors incorporated the fix and published advisories and packages, reducing the window of exposure for many users.
- Vendored stdlib copies embedded in long‑lived applications can remain vulnerable even after the system Go runtime is patched. This is the most frequent operational trap: products built once and left unchanged can be exploited even if the underlying platform is patched. Developers should avoid long‑term vendoring of unpatched stdlib code or ensure a policy to rebuild and redeploy regularly.
- Detection is non‑trivial: because the attack involves seemingly valid gzip header structures, basic signature‑based filters may not detect malicious archives. Behavioral controls (timeouts, sandboxing, resource limits) are stronger mitigations than signature matching alone.
Recommended timeline for teams
- Within 24–72 hours: identify exposed services and apply vendor patches or rebuild affected binaries with a fixed Go release. Implement emergency process isolation if rebuilding isn’t possible.
- Within 1–2 weeks: roll out full updates across environments (staging → canary → production) and audit images and vendor products for vendored stdlib usage.
- Within 1–3 months: add the issue class (uncontrolled recursion / decompression DoS) to threat modeling and secure coding guidance; adopt CI checks that detect vendored stdlib packages and flag outdated Go versions.
Final analysis and takeaways
CVE‑2022‑30631 is a classic example of how a small logic choice in a standard library — recursion versus iteration — can create a meaningful denial‑of‑service vector at scale. The vulnerability is not exotic, and the fix was straightforward; yet the operational reality of distributed systems, vendored dependencies and slow rebuild cycles means remediation requires coordinated work across development, ops, and security teams.Key takeaways:
- Patch build toolchains and rebuild artifacts promptly — updating a system runtime is not always sufficient when code is vendored or statically linked.
- Treat decompression operations as untrusted input: run them in restricted contexts, with timeouts and resource caps.
- Include standard library vulnerabilities in SBOM and SCA scans, and monitor vendor advisories for downstream implications.
Conclusion
CVE‑2022‑30631 underscores that even widely used standard libraries can harbor availability‑only vulnerabilities with outsized operational impact. The fix is available and straightforward — replace recursion with iteration in the gzip reader — but full remediation requires a disciplined program: inventory, patch, rebuild, and isolate. Operators who treat decompression as a privileged operation (sandboxing, limits, and dedicated workers) will be far more resilient than those who do not. Apply the Go security releases, update vendor packages, and harden decompression paths to remove this attack surface from your critical services. (go.googlesource.com)
Source: MSRC Security Update Guide - Microsoft Security Response Center