Go Gob Decoder DoS: CVE-2024-34156 Stack Exhaustion and Mitigation

  • Thread Author
A critical availability weakness in Go’s standard library — tracked as CVE-2024-34156 — lets an attacker reliably crash a process that decodes untrusted gob data by driving the decoder into stack exhaustion. The flaw is simple in concept but serious in consequence: calling encoding/gob’s Decoder.Decode (or DecodeValue) on a crafted payload containing extremely deep nesting causes unbounded recursion that the runtime cannot recover from, producing a fatal stack overflow and terminating the program. This is a pure Denial‑of‑Service (DoS) vector affecting applications that accept GOB-encoded input from untrusted sources; it was fixed upstream in Go release updates and has been cataloged by vendors and distributions.

Blue neon poster shows a surprised beaver beneath “STACK OVERFLOW” and CVE-2024-34156 amid binary rain.Background / Overview​

The Go standard library's encoding/gob package provides a binary serialization format used by many Go programs for RPC, inter-process data exchange, and persistence. Gob is compact and convenient inside a Go ecosystem, but like all deserializers it must be careful when processing data from outside trusted boundaries.
CVE-2024-34156 is a follow‑on to a previous gob weakness (CVE-2022-30635) that exposed the same class of risk: uncontrolled recursion while decoding deeply nested structures. In this newest report, certain code paths in the decoder fail to limit nesting depth in all cases, allowing a maliciously crafted payload to force the decoder into deep recursion and eventually exhaust the goroutine stack. The runtime prints a fatal error (stack overflow) and the process exits — there is no normal, graceful error return for the application to handle. The issue was tracked privately and disclosed in the Go project’s issue tracker and fixed in maintenance releases.
Key high‑level facts:
  • Vulnerability type: Stack exhaustion / uncontrolled recursion in encoding/gob Decoder.Decode.
  • Primary impact: Denial‑of‑Service — process termination (fatal stack overflow).
  • Affected releases: versions before the patches landed in the 1.22 and 1.2d in the maintenance releases that followed the advisory).
Community and operations teams picked up the issue quickly; public vulnerability databases, distribution advisories, and the Go project note the same root cause and remediation path. Forum and community archives also show ongoing attention to Go parser/decoder DoS variants, underscoring the operational reach of serialization bugs.

How the bug works — technical analysis​

Decoder recursion and ignored fields​

The encoding/gob decoder parses types and values recursively. Every time the decoder encounters a nested value (for example, a slice of slice of slice ...), the decoding path recurses deeper. In normal operation this recursion is bounded by the structure depth of legitimate data, but an attacker can craft a gob stream with many layers of nested containers.
In vulnerable code paths the implementation did not consistently enforce the same ignore‑depth limits that other encoders/decoders adopted. That allowed the decoder to follow recursive decode code paths far deeper than anticipated, consuming the goroutine’s stack until the Go runtime’s stack limit was exceeded and the runtime aborted with a fatal "stack overflow". The runtime fatal is not a recoverable panic — it terminates the process.

Why recover() and normal error handling can't save you​

A common defensive idea is to use defer/recover around decoding so the application can turn failures into errors and keep running. That works for ordinary panics (runtime.panic), but a stack overflow is a fatal runtime error produced by runtime.throw/runtime.fatal, not a standard panic. When a goroutine hits the runtime's stack ceiling the runtime prints a fatal error and exits; there is no opportunity to recover. In short, you cannot reliably trap or recover from a stack‑exhaustion crash inside the same process.
This reality forces operators to rely on process isolation and runtime updates (or preventative input controls), not local panic handling, when mitigating this category of flaw.

Scope and systems affected​

  • Any Go program that imports and uses encoding/gob.Decoder to process data that can be influenced by untrusted actors is in scope. That includes RPC servers that use net/rpc with gob codecs, internal daemons that accept gob over sockets, CLI tools that decode uploaded gob blobs, and some third‑party libraries that call gob decode on data from network sources.
  • The vulnerability is in the standard library, so it surfaces anywhere the affected Go runtime or stdlib artifact is used. This includes container images, cloud agents, and distribution packages that include vulnerable Go binaries or statically link the standard library. Multiple vendor and distro advisories flagged packages and images as affected, demonstrating downstream exposure across ecosystems.
  • Exploitability: the attack requires the ability to supply crafted gob payloads to the vulnerable decoder (often achievable via network endpoints, RPC interfaces, or file uploads). No authentication is required in many deployment patterns, which explains the high availability impact ranking in vulnerability trackers.

Severity, measurable risk, and CVSS​

Vulnerability trackers assigned a high severity rating driven by availability impact: successful exploitation yields total loss of availability for the impacted process (process exit). Several public vulnerability listings and vendors show a CVSS v3.1 base score in the high range for this issue and treat the bug as an availability-only impact (no confidentiality or integrity loss). Operators should treat this as a high‑priority patch for systems that process untrusted gob input.

Evidence and vendor responses​

  • The Go project tracked the issue privately and opened a public issue describing the condition; the fix aligns the gob decoder’s ignore‑depth checks with other protections and landed as part of the follow‑up maintenance releases. The GitHub (Go) issue and internal change list are the authoritative upstream artifact for the fix.
  • Distribution vendors scanned and produced advisories and package updates. Ubuntu, Red Hat, and others published entries and delta patches as distributions rolled the fixed library and rebuilt dependent packages. These vendor advisories are important for operators who rely on packaged Go toolchains or distro-provided binaries.
  • The broader security community (oss‑security lists, CVE aggregators) captured the release notes and recommended upgrades to the fixed versions. These sources also document the connection to earlier gob vulnerabilities in 2022.

Practical detection and triage​

1. Inventory: where is gob used in your estate?​

  • Search your codebase for imports of "encoding/gob" and calls to Decoder.Decode / DecodeValue.
  • Scan compiled binaries with tooling that can report linked stdlib versions (govulncheck and similar tools identify vulnerable symbols and traces). govulncheck scans already highlight GO-2024-3106 traces in common call chains.

2. Identify reachable decode entry points​

  • Focus on network-facing RPC endpoints, file‑import handlers, or places where user-supplied data reaches gob.Decoder.
  • Prioritize services that operate with elevated privileges or inside multi‑tenant contexts where a single crash can cascade.

3. Look for crash indicators​

  • Runtime logs showing messages like "runtime: goroutine stack exceeds ... byte limit" or "fatal error: stack overflow" are direct signs of stack exhaustion. These should trigger immediate containment and patching. The runtime message is unambiguous; when seen in production logs, assume a DoS exploit attempt or accidental malformed input triggered the crash.

Mitigation and remediation (actionable guidance)​

The only reliable remediation is to update the Go toolchain / runtime to the patched releases. Because this is a standard‑library bug, the fix can come via upstream Go releases or downstream distribution packages.
  1. Patch/upgrades (primary mitigation)
    1. Update to the fixed releases in your release line. Upstream guidance lists the maintenance releases that include the fixes; verify your specific minor version and apply the appropriate patch. Upstream Go release notes and the GO‑2024‑3106 advisory identify the fixed versions for the affected branches.
    2. Rebuild and redeploy any statically linked binaries (the standard library is compiled into binaries), container images, or agents that embed the Go runtime. Ensure your CI builds fetch the patched Go toolchain before building artifacts.
  2. Temporary mitigations (when immediate patching is not possible)
    • Process isolation: Run gob decoding inside a sandboxed helper process with low privileges and monitored lifecycle; if the helper process crashes due to stack exhaustion the supervisor can restart it without bringing down the main service. Because the stack overflow kills just the process, running the decode in a separate process bounds the blast radius.
    • Network and input controls: Harden ingress points that accept gob content. Apply authentication, rate‑limits, and conformance checks to reduce exposure to arbitrary payloads. If feasible, restrict the set of callers that can submit gob payloads.
    • Reject untrusted gob data: Replace gob with safer, less‑risky serialization formats for untrusted input (for example, well‑validated JSON or protocol buffers used with strict schema validation). If gob must be used, only accept it from known, trusted peers.
    • Separate decoding threads/processes: Because recovery is impossible for stack overflow inside the same process, decoding in a short‑lived subprocess is a practical containment pattern. The subprocess can be killed and restarted without affecting the primary service.
  3. Detection and monitoring
    • Add runtime crash detection and alerting for the specific fatal messages; ensure on‑call can respond to repeated crash patterns, which may indicate active exploitation attempts.
  4. Long‑term engineering hardening
    • Avoid accepting arbitrary serialized values from untrusted sources. Prefer explicit, schema‑driven parsers and validation of shapes and depth limits before full deserialization.
    • Contribute tests and fuzzing harnesses for deserializers. The Go community has mitigations like depth limits in other encoders; add unit tests for extreme nesting cases to your libraries.

Responsible disclosure and patch timeline​

The issue was reported to the Go project and tracked internally (private tracking for coordinated disclosure) before fixes were landed and published in maintenance releases. Publicly visible issue and code review references indicate the path to remediation and the engineering rationale for the chosen fix (covering missed cases when checking ignore depth). Distribution and security databases began publishing advisories almost immediately after the upstream fixes were released, enabling downstream vendors to ship updates.

Real‑world operational considerations and risks​

  • High availability contexts: In multi‑tenant services and platform agents, a single exploit can repeatedly crash processes, causing customer‑visible outages and operational churn.
  • Embedded systems and long‑lived daemons: For services designed to run continuously, a crash that the process cannot recover from is especially disruptive; even short downtime for restarts may trigger failover churn or loss of in‑flight state.
  • Supply‑chain exposure: Because the standard library fix only eliminates the bug in newly built binaries, containers and images built before the fix remain vulnerable until they are rebuilt and redeployed. This expands the window of risk for operators who rely on prebuilt images or packaged runtime artifacts. Distribution advisories show the downstream rebuilds that maintainers must perform.

Practical checklist for operators (quick action list)​

  1. Inventory all services that import encoding/gob or perform gob decoding.
  2. Identify the Go version used to build each binary and whether the stdlib was updated since the advisory. Use govulncheck or similar to flag GO‑2024‑3106 traces.
  3. Prioritize patching services that accept data from external or untrusted sources.
  4. If immediate patching isn’t possible, isolate gob decoding into a helper process and add ingress filtering and rate limits.
  5. Rebuild and redeploy container images and compiled artifacts with a patched toolchain.
  6. Add monitoring rules for runtime fatal messages and configure alerts for repeated crashes.

Strengths and weaknesses of the upstream fix​

  • Strengths
    • The upstream fix introduces consistent depth checks that match protections used in other decoders, reducing future attack surface for deeply nested inputs.
    • The Go project’s maintenance release model allowed the fix to flow into both active release branches so operators could pick the appropriate maintenance update for their environment.
  • Remaining risks and caveats
    • Patch rollout inertia: many organizations run prebuilt images or third‑party binaries; those artifacts must be rebuilt to benefit from the fixed stdlib. Distributions and vendors must rebuild and republish, which takes time.
    • Runtime fatal errors are fundamentally destructive: as long as stack exhaustion is possible in any code path that processes untrusted input, the risk of process‑level DoS remains unless input is constrained or decoding is moved out of the main process.
    • There is a broader class of deserialization and parser DoS issues (e.g., ReDoS, decompression bombs, deep recursion in other parsers) — fixing gob reduces one vector but does not eliminate the general class of availability risks that come from processing complex or recursive input structures.

Conclusion​

CVE-2024-34156 is a clear operational reminder: deserialization is dangerous when the parser assumes well‑formed and modestly sized input. The Go project fixed a concrete crack in the gob decoder that could be exploited to produce fatal stack exhaustion, but the practical defense extends beyond a single patch. Operators must inventory where gob decoding happens, update and rebuild artifacts with the patched stdlib, and where necessary isolate decoding from critical service processes.
If your services accept gob-encoded content from any untrusted network or user channel, treat this as an urgent patch-and-rebuild task and implement process isolation as a stopgap until every affected artifact is rebuilt with the fixed Go release. The underlying lesson is operational and perennial: serialization parsers must explicitly limit depth and complexity, and defensive architecture must assume attackers will try to push parsers to their limits.

Source: MSRC Security Update Guide - Microsoft Security Response Center
 

Back
Top