Go math/big SetString CVE-2022-23772 Patch Prevents Unbounded Memory Growth

  • Thread Author
The Go standard library’s math/big package contained a subtle but dangerous bug in the Rat.SetString function that could be triggered by crafted input to force unbounded memory growth and crash services that parse or accept user-controlled rational numbers. The flaw — tracked as CVE-2022-23772 — was fixed in the Go project’s minor point releases Go 1.16.14 and Go 1.17.7; maintainers credit OSS‑Fuzz and a community reporter for discovery and the Go project for a targeted patch.

Go logo with a rat, binary digits, a stack of blocks, and CVE-2022-23772 security warning.Background​

What part of Go is affected​

Go’s math/big package implements arbitrary‑precision integers (big.Int), rationals (big.Rat), and related arithmetic. The package exposes convenience methods such as (*Rat).SetString, which parses a textual rational representation (examples: "3/4", "-10/3", or "0") into a big.Rat value. Because math/big supports unbounded precision, parsing arbitrary text can require allocating memory proportional to the numeric magnitude represented by that text.

The vulnerability in one sentence​

A parsing path in (Rat).SetString failed to correctly guard against an integer overflow in its internal computation that estimates the sizes needed to hold a parsed numerator and denominator; a crafted input could force that estimation to overflow and lead the runtime to attempt huge allocations, producing uncontrolled memory consumption* and enabling a denial‑of‑service condition.

The technical story: how SetString can be abused​

Parsing, allocation and the overflow​

When SetString parses an input it must convert string digits into big.Int limbs and allocate enough space to hold those limbs. The vulnerable code computed sizes based on digit counts and then multiplied or shifted to derive the number of machine words (limbs) to allocate. Under certain crafted inputs those arithmetic computations could overflow the intermediate integer type used for size calculations. When an overflow occurs the resulting, truncated value can be small or wildly incorrect, but the code downstream can still try to allocate based on the (incorrect) value or otherwise mismanage buffer sizes — ultimately causing uncontrolled memory allocation attempts or other out‑of‑bounds behavior. The Go patch prevents the overflow by validating and bounding the intermediate calculations and refusing to proceed when sizes would wrap or exceed safe limits.

Patch details and upstream fix​

The Go project landed a targeted change to math/big to prevent the overflow in (*Rat).SetString. The fix is credited to the OSS‑Fuzz discovery and reporting by Emmanuel Odeke, with the patch reviewed and merged by Go maintainers (change list and commit message contain the rationale and reviewers). That change is referenced in the official release announcement for the Go 1.17.7 and 1.16.14 releases, which explicitly list “math/big: prevent large memory consumption in Rat.SetString” as one of the security fixes.

Impact: availability and exploitation risk​

Practical consequences​

The vulnerability is a classic resource‑exhaustion denial‑of‑service (DoS). If an attacker can influence the input passed to (*Rat).SetString — for example, via an API that accepts numeric strings, or through a service that parses rational numbers from untrusted sources — they can cause the target process to grow its memory usage without bound until the host runs out of memory, the process is terminated by the OS, or service responsiveness collapses. The result is a total loss of availability for the affected component while the attack persists, and a persistent outage if the system cannot recover gracefully. Multiple vendors’ security advisories characterize the impact similarly.

Severity and scoring​

Vulnerability databases and vendor advisories generally scored CVE‑2022‑23772 as high‑severity for availability impact. Typical CVSS v3.1 assignments give a base score of 7.5 (High) with the vector indicating a network‑accessible vector and no required privileges. Distribution maintainers (Ubuntu, SUSE, Red Hat, Amazon Linux, and others) published advisories and backports that reflect the urgent need to remediate.

Exploit availability and practical likelihood​

As of public advisories and vulnerability trackers, there is no widely‑reported, reliable public proof‑of‑concept (PoC) exploit published that weaponizes CVE‑2022‑23772 in the wild. Scanners and threat feeds indicate detection signatures were added to enterprise scanners over time, but published exploitation activity appears limited. Risk teams should treat this as a high‑impact, moderately likely risk: the bug is straightforward to trigger wherever user input flows into SetString, but real‑world exploitation requires an application to expose that call path to untrusted inputs. Public trackers and container vulnerability databases list low EPSS/exploitability scores compared with more actively exploited CVEs.
Note: absence of a public PoC does not mean the vulnerability is theoretical. The underlying conditions are easy to reason about for an attacker, and the potential impact is immediate for services that parse untrusted numeric strings.

Who and what is affected​

Affected Go versions​

  • All Go releases before 1.16.14 (i.e., any 1.16.x older than 1.16.14).
  • All 1.17 branch releases from 1.17.0 up to but not including 1.17.7.
The Go project’s security announcement lists these exact ranges and identifies the fix shipping in the 1.16.14 and 1.17.7 releases.

Downstream impact and packaged distributions​

Because Go is both a compiled language and a provider of runtime libraries used at build time, two classes of real‑world systems can be affected:
  • Applications compiled with a vulnerable Go toolchain that embed the vulnerable math/big implementation into their binaries. Many Go binaries are statically linked; if an upstream project was built with an affected Go version and that binary is deployed, it can contain the vulnerable code even when run on systems whose package manager offers a patched golang package. Rebuilding with an updated compiler version is the correct fix for such binaries.
  • Operating system or vendor Golang packages (Debian, Ubuntu, Red Hat, SUSE, Amazon Linux, etc.) that distribute the vulnerable standard library for use at runtime or by developers. Those maintainers released patches and advisories; operators using packaged golang should install vendor updates.
A number of vendor advisories reference CVE‑2022‑23772 as affecting downstream services and products that embed Go components (for example, container platforms, telemetry agents, or storage management tools). Operators of such appliances should consult vendor bulletins and rebuild or upgrade images as advised.

How to detect exposure in your environment​

  • Inventory Go runtimes and binaries. Determine which systems, CI pipelines, and build hosts use Go toolchains older than 1.16.14 or 1.17.7. Remember that static binaries compiled with older toolchains can carry the vulnerable code even if the host's package for golang is patched.
  • Scan deployed binaries for embedded Go runtime versions. Many compiled Go binaries include version strings; search for "go1.16" or "go1.17" markers and check build metadata. If a binary was built with an affected toolchain, plan a rebuild against a fixed compiler.
  • Use software composition analysis and container image scanners. Popular vulnerability scanners added detection rules for this CVE; run up‑to‑date scans across images and base containers and address reported findings in CI/CD pipelines.
  • Audit application inputs. Locate code paths that call (*big.Rat).SetString (or that call wrappers which call it). If those paths accept external input (HTTP payloads, IPC, RPC, messaging), treat them as high‑risk and prioritize remediation. Static code analysis tools and SAST rule sets now commonly include detections for avoiding SetString where untrusted input is possible.

Mitigation and remediation: step‑by‑step​

  • Priority upgrade
  • Upgrade the Go toolchain: ensure build and developer machines use Go 1.16.14, Go 1.17.7, or any later supported release that includes the math/big fix. The Go project specifically called out these releases as the security update carriers.
  • For packaged distributions, apply vendor updates (Debian/Ubuntu/Red Hat/SUSE/Amazon Linux patches) that backport the fix into distribution packages. Check your OS vendor’s security tracker and apply the recommended package upgrades.
  • Rebuild and redeploy binaries that were compiled with vulnerable toolchains
  • If you deploy precompiled Go binaries or third‑party appliances based on Go, rebuild those binaries with a patched Go release and redeploy. Static linking means simply patching the runtime on the host is not enough for older binaries. Confirm via build metadata that the new binaries are linked to the patched standard library.
  • Short‑term application mitigations (if you cannot upgrade immediately)
  • Add strict input validation: reject unusually long numeric strings and enforce sane digit limits for numerator and denominator before calling SetString.
  • Enforce per‑request and process memory caps: use container memory limits, ulimit, or job supervisors so a single request cannot starve the host.
  • Rate‑limit endpoints that parse numeric input and instrument memory usage alerts so anomalous growth is detected early.
  • Consider sandboxing parsing operations in a separate process with constrained memory and CPU to contain a crash to a small component. These are mitigations only — upgrading or rebuilding remains the correct fix.
  • Detection and post‑remediation verification
  • After patching, run regression tests that parse a range of numeric inputs (including extreme boundary cases) and verify memory usage remains bounded.
  • Re‑scan images and packages with vulnerability scanners to ensure the CVE is no longer flagged in deployed artifacts.

Operational notes and developer guidance​

Why fuzzing and responsible disclosure mattered here​

This vulnerability is a textbook example of the value of continuous fuzzing. OSS‑Fuzz — Google’s continuous fuzzing service — discovered the issue and community disclosure through Emmanuel Odeke led to a prompt patch. The incident highlights the practical benefit of automated fuzzing on critical language runtimes and the healthy feedback loop between fuzzing projects, open source maintainers, and responsible reporters. Teams should consider integrating fuzz testing for parsing code and libraries that accept untrusted input.

Coding practices to avoid similar problems​

  • Avoid calling SetString on parser code paths that directly accept untrusted input. Prefer explicit parsing with strict digit and length checks.
  • When using arbitrary‑precision types, always pre‑validate textual inputs for maximum length and structure before attempting conversions.
  • Put a budget on memory or operations when dealing with potentially untrusted numeric representation: e.g., parse digit counts and reject anything beyond a safe threshold before allocating heavy structures.

Supply‑chain and build considerations​

Remember that Go’s compiled binaries can carry vulnerable standard library code. An organization’s software supply chain must include:
  • controlled build environments that pin Go toolchain versions,
  • a rebuild strategy for critical third‑party binaries built with vulnerable compilers,
  • CI pipelines that fail when base images or build toolchains are out of date.
This CVE demonstrates that keeping runtime and toolchain versions current is as important as OS and library patching.

Evidence and verification: what we checked​

  • The Go project’s security announcement for the 1.16.14 and 1.17.7 minor releases explicitly lists the math/big fix for preventing large memory consumption in (*Rat).SetString. That announcement ties the change to CVE‑2022‑23772 and describes the credit to OSS‑Fuzz and Emmanuel Odeke.
  • The Go change list and commit (referenced in the Go vulnerability database) show an authored patch with a short commit message “math/big: prevent overflow in (*Rat).SetString” and reviewers. The commit metadata and CL confirm the code‑level fix and the intent to prevent overflow and unbounded allocation.
  • Multiple independent vulnerability databases and vendor trackers (NVD, AWS ALAS, Debian security tracker, SUSE, Ubuntu) list CVE‑2022‑23772 with the same affected‑version ranges and emphasize availability impact. This convergence across independent trackers supports the factual claims about affected versions and impact.
  • Scanners and vulnerability feeds that track exploit activity do not show large‑scale exploitation of this CVE in the wild; public PoC code has not been reliably identified at the time of writing, but detection and scanner signatures were added to enterprise scanners after the bug disclosure, which is consistent with a vulnerability of operational concern. Operators should not rely on “no PoC” as a security guarantee — the exposure is real wherever SetString deals with untrusted data.

Strengths of the response and remaining risks​

Notable strengths​

  • The Go project patched the bug in the standard library quickly and documented the release in the official announce posts. The commit and CL are public and show direct remediation, which helps operators verify fixes and decide upgrade paths.
  • Distributors and large vendors incorporated the fix into packaged updates and advisories, enabling system administrators to remediate through normal OS package management where appropriate.

Residual risks and caveats​

  • Static binaries built with vulnerable toolchains remain a vector until rebuilt. Simply patching host packages will not fix those artifacts; organizations must inventory binaries and ensure rebuilds happen where necessary.
  • The underlying class of bug — integer overflow in allocation calculations — can appear in other parsing routines. Organizations should review parsing code paths beyond the specific SetString calls. Fuzzing and stricter input checks are advisable defenses.
  • Even when no public PoC exists, the conceptual exploit is straightforward for attackers who can submit crafted numeric strings to exposed services. This makes timely remediation and defensive controls (input validation, resource limits, rate limiting) important interim steps.

Action checklist for defenders (fast‑remediation playbook)​

  • Inventory: identify servers, build hosts, and containers that run Go or contain Go binaries.
  • Patch: apply vendor patches or upgrade to Go 1.16.14 / 1.17.7 or later.
  • Rebuild: compile any in‑house Go binaries with an updated toolchain and redeploy.
  • Harden: add input validation to reject extreme numeric strings; enforce memory caps and rate limits.
  • Scan: run static and dynamic scans to find remaining instances of SetString or calls into math/big from untrusted inputs.
  • Monitor: add alerts for rapid memory growth and anomalous allocation patterns in services that parse numbers.

Conclusion​

CVE‑2022‑23772 is a compact but high‑impact example of how arithmetic assumptions in parsing code can translate directly into availability risks. The Go project’s response — a focused code change and timely minor releases — closed the immediate hole, but the operational work of finding and rebuilding vulnerable binaries and hardening input‑handling remains with operators and developers. The incident reaffirms three cardinal rules for resilient software: keep build toolchains current, treat input parsing as a potential attack surface, and use automated testing (including fuzzing) to find the edge cases that can turn harmless parsing into a denial‑of‑service weapon.


Source: MSRC Security Update Guide - Microsoft Security Response Center
 

Back
Top