A heap buffer overflow in zlib's inflate.c — tracked as CVE-2022-37434 — put one of the most widely embedded pieces of software on the planet back in the security spotlight. zlib underpins gzip/zip decompression across operating systems, container base images, language runtimes (Python, Node.js, Java, Go via cgo), and thousands of applications that never advertise it as a dependency. The bug lives in the gzip header parsing path used by inflateGetHeader(), and a crafted gzip stream with an oversized "extra field" can cause zlib to read or write past the bounds of a heap-allocated buffer — typically crashing the consuming process, and in narrower conditions corrupting adjacent heap memory. Because zlib is so deeply vendored and statically linked across the software supply chain, the practical challenge for most organizations wasn't understanding the bug — it was finding every place a vulnerable copy was hiding.
What's actually vulnerable
zlib exposes an optional API, inflateGetHeader(), that lets a calling application ask the decompressor to populate a gz_header structure with metadata from a gzip stream — including the OS byte, timestamp, filename, comment, and an arbitrary "extra field" (the FEXTRA flag in the gzip format). When a caller sets head->extra to a buffer and head->extra_max to that buffer's size, zlib copies extra-field bytes from the compressed stream into the caller's buffer as it decodes.
The flaw is in the bookkeeping zlib uses to track how many extra-field bytes it has already copied across multiple calls to inflate(). When the extra field is large enough to span more than one inflate() invocation — which is entirely attacker-controllable, since the extra field length is encoded in the stream itself — the internal accounting can under- or over-count how much has already been written. That miscalculation lets zlib compute a destination offset that lands outside the caller-supplied extra buffer, resulting in a heap-based buffer overflow (or over-read, depending on the exact code path and buffer layout). The attacker doesn't need to control the contents Written past the buffer in a useful way for classic memory-corruption exploitation — but they do control the size and shape of the malformed gzip stream that triggers it, which is enough to reliably crash a process and, under certain heap layouts, disturb adjacent allocations.
Critically, this is not a bug in every zlib decompression call. It only triggers when the calling application explicitly opts into inflateGetHeader() and supplies a fixed-size extra buffer. Bare inflate()/uncompress() usage — the vast majority of zlib call sites in the wild — never touches this code path at all. That distinction matters enormously when triaging exposure, and it's also why this CVE became a case study in over-broad severity scoring (more on that below).
Affected versions and components
- Vulnerable range: zlib versions from roughly 1.2.0.4 (when
inflateGetHeader()was introduced) through 1.2.12, the version shipped just before the fix. - Fixed in: a patch applied to the zlib source tree in mid-2022, with a cleaner, more complete rewrite of the header-extra handling shipped in the official zlib 1.2.13 release (October 2022) and carried forward into 1.3 and later.
- Where it hides in practice: zlib is rarely a "top-level" dependency you'd find by reading a package.json or requirements.txt. It's statically linked into libpng, libcurl, OpenSSH, PHP, countless Node.js and Python native extensions, container base images (Debian, Alpine, Ubuntu, distroless), firmware images, and language runtime binaries themselves (CPython's
zlibmodule and Node's built-inzlibmodule both link against a bundled or system copy). Any of these can carry a vulnerable zlib without it appearing as a discrete, updatable dependency in a manifest file. - Real-world exploitability gate: exposure requires the consuming application to actually call
inflateGetHeader()withhead->extraset — used by things like certain PNG metadata readers, some HTTP/gzip-aware proxies, and custom gzip-header inspection tools. General-purpose decompression call sites are not affected.
CVSS, EPSS, and KEV context
CVE-2022-37434 became almost as notable for its scoring controversy as for the bug itself. NVD's automated/analyst scoring assigned a CVSS v3.1 base score of 9.8 (Critical), using a vector implying network attack vector, no privileges required, and high impact to confidentiality, integrity, and availability. Several downstream vendors pushed back hard on that rating. Red Hat, Debian, and other distro security teams scored the same flaw considerably lower — Red Hat rated it Low to Moderate impact for most of its affected packages — arguing that a memory-safety bug gated behind a specific, non-default API usage pattern doesn't meet the bar for a network-exploitable critical, and that practical confidentiality/integrity impact was unproven for the vast majority of real deployments.
This divergence is a useful teaching moment: NVD's base score reflects a worst-case theoretical exploitation path, not your environment's actual exposure. Two vulnerability scanners can both be "correct" and still hand you wildly different severities for the same CVE if one stops at the NVD score and the other accounts for how the vulnerable function is actually reached.
On the exploitation-likelihood side, EPSS scores for CVE-2022-37434 have generally sat well below the threshold that indicates active, widespread exploitation interest — consistent with a bug that is real and worth patching, but that lacks an efficient, generically weaponizable exploitation path for remote code execution. It has not appeared on CISA's Known Exploited Vulnerabilities (KEV) catalog, and no credible reports of in-the-wild exploitation have surfaced since disclosure. The realistic risk profile is best summarized as: meaningful denial-of-service potential for the narrow set of applications that call the affected API with attacker-reachable input, and negligible risk for the much larger population of applications that only use zlib for plain compression/decompression.
Timeline
- ~2004:
inflateGetHeader()and the gzip extra-field handling are introduced into zlib, carrying the latent bug forward through more than a decade of releases. - March 27, 2022: zlib 1.2.12 is released — the last version before the fix, and the version most commonly flagged by scanners.
- Mid-2022: The buggy extra-field bookkeeping is identified and a fix is committed to the zlib source repository, ahead of a full point release.
- August 2022: CVE-2022-37434 is publicly assigned and published in the NVD, triggering a wave of advisories across Linux distributions, container registries, and language ecosystems.
- August–September 2022: Debian, Ubuntu, Red Hat, Alpine, and major cloud/container base image maintainers ship patched builds; disagreement over NVD's Critical rating plays out publicly in distro trackers and security mailing lists.
- October 13, 2022: zlib 1.2.13 is officially released, incorporating a more thorough rewrite of the header-parsing logic rather than the interim point patch, closing residual edge cases.
Remediation steps
- Inventory every copy of zlib, not just the obvious one. Direct package manager entries are the easy part. Look for statically linked copies inside application binaries, container base layers, vendored native modules (Node.js
node_moduleswith prebuilt binaries, Python wheels bundlinglibz), firmware, and third-party SDKs. An SBOM that only reflects your top-level manifest will systematically miss this class of dependency. - Upgrade to zlib 1.2.13 or later. Treat the interim 1.2.12 patch as a stopgap only; standardize on 1.2.13+ (or the current 1.3.x line) wherever you control the build.
- Rebuild and relink, don't just repoint a manifest. Because zlib is frequently statically linked, bumping a version string in a lockfile doesn't help — binaries need to be recompiled against the patched library, and container images need fresh base layers, not a package-manager patch on top of a stale binary.
- If you can't patch immediately, remove the attack surface directly. If your application doesn't need gzip extra-field metadata, don't set
head->extrawhen callinginflateGetHeader()— this fully avoids the vulnerable code path without requiring a library upgrade. - Re-scan and regenerate SBOMs after remediation. Confirm the patched version is actually present in the rebuilt artifact, not just declared in source — especially for base images that get rebuilt on a delayed cadence relative to your application code.
- Track distro-specific advisories, not just the upstream CVE. Debian, Red Hat, and Ubuntu backport fixes into their own versioning schemes, so a version-number check against upstream zlib releases alone will produce false positives on already-patched distro packages.
How Safeguard Helps
Deeply vendored dependencies like zlib are exactly where CVE noise drowns out real risk — most teams either ignore CVE-2022-37434-class findings entirely or burn engineering time patching instances that were never reachable in the first place. Safeguard's reachability analysis traces whether your application actually invokes inflateGetHeader() with an attacker-influenced extra buffer, so you can immediately separate the handful of genuinely exposed services from the much larger set where the vulnerable code path is dead weight. Our SBOM generation and ingest pipeline is built to surface statically linked and transitively vendored libraries like zlib — not just top-level manifest entries — so a hidden copy in a base image or a bundled native module doesn't slip through unnoticed. Griffin AI correlates that reachability signal with CVSS, EPSS, and exploit-availability data to produce a prioritized, risk-ranked queue instead of a flat CVE list. When a fix is confirmed necessary, Safeguard can open an auto-fix PR that bumps the vendored or linked zlib version and reflects the change in your updated SBOM, closing the loop from detection to remediation without manual triage.