Safeguard
Vulnerability Analysis

WebP (CVE-2023-4863) Explained: The libwebp Heap Overflow That Patched the Web

CVE-2023-4863 was an actively exploited heap buffer overflow in libwebp's Huffman decoder. Because the codec is vendored everywhere, one bug forced emergency patches across browsers and apps.

Marcus Chen
Security Researcher
6 min read

CVE-2023-4863 is a heap buffer overflow in libwebp, the open-source library that nearly every browser and countless desktop apps use to decode WebP images. Rated CVSS v3.1 8.8 (High) and classified as CWE-787 (out-of-bounds write), it could be triggered by nothing more than rendering a malicious image on a web page. It was a zero-day exploited in the wild before the fix shipped, and because libwebp is vendored into so many unrelated products, a single upstream commit set off a cascade of independent emergency releases.

Timeline and impact

On September 11, 2023, Google shipped an emergency Chrome update (116.0.5845.187) acknowledging active exploitation. NVD published the entry on September 12. CISA added it to the Known Exploited Vulnerabilities catalog with a short remediation deadline, reserved for confirmed in-the-wild abuse. Over the following days Mozilla patched Firefox and Thunderbird, Microsoft patched Edge on its own cadence, and Debian and Fedora updated their shared libwebp packages. The messy part was everything downstream: Electron apps and anything embedding Chromium each shipped their own bundled copy of libwebp and had to rebuild independently. A closely related identifier, CVE-2023-5129, was assigned during the confusion and later treated as a duplicate, which added to the noise.

The exploitation context raised the stakes further. The bug surfaced amid research into a mobile exploit chain of the kind associated with commercial spyware vendors, where a zero-click image delivered through a messaging app is a prized delivery mechanism precisely because rendering happens automatically. That is why a "just an image decoder" bug drew the urgency normally reserved for kernel or browser-engine zero-days: the victim does not click anything, does not download anything obvious, and does not get a warning — the image simply arrives and is parsed. It is also why the duplicated CVE identifier mattered operationally. Teams tracking only one of the two IDs, or waiting for their scanner to reconcile them, risked believing they were covered while a bundled copy went unpatched under the other number.

Technical root cause

The flaw lives in libwebp's lossless decoder, specifically the Huffman-table construction routine BuildHuffmanTable. To decode a lossless WebP, the library builds lookup tables sized according to the code lengths declared in the image's Huffman header. The allocation assumed the declared code lengths were well-formed.

A crafted WebP could specify a combination of code lengths that required more second-level table entries than the buffer libwebp had allocated. When the decoder filled the table, it wrote past the end of that heap allocation, corrupting adjacent memory:

1. Parse Huffman code lengths from attacker-controlled WebP header
2. Allocate lookup table sized from an under-counted worst case
3. Populate table entries from the (malicious) code lengths
4. Entry count exceeds allocation  -> out-of-bounds heap write

Because the corruption happens during decode, before any application-level validation runs, the attacker only needs the victim's software to attempt to render the image. Combined with the right heap grooming, an out-of-bounds write of controlled data is a strong primitive for full code execution — which is why it commanded a zero-day price and appeared in a real exploit chain. The fix in libwebp 1.3.2 corrected the bounds computation so the table allocation accounts for the true worst case implied by the declared code lengths.

How to detect if you are affected

  • The OS package is the easy half. dpkg -l | grep libwebp or rpm -q libwebp tells you about the shared system library. Patch it and every dynamically linked consumer benefits at once.
  • The vendored copies are the hard half. Electron apps, Chromium Embedded Framework apps, mobile SDKs, and image-processing tools frequently bundle their own libwebp inside the app package, several directories away from anything the OS package manager knows about. A manifest-only scan reports "patched" while an unpatched Slack.app or /opt/vendor-tool remains exploitable.
  • The real detection question is: does any artifact anywhere in my environment bundle libwebp at any depth, independent of the OS copy?

That is exactly the question shallow scanners cannot answer. Safeguard's software composition analysis resolves deep dependency graphs and reports the full path from an artifact's root down to a bundled libwebp node, so vendored copies do not disappear into a manifest gap.

Remediation and patched versions

  1. Update the OS package to a build incorporating libwebp 1.3.2 or later and restart consumers.
  2. Update every app that bundles its own copy — browsers, Electron apps, and any tool that statically links or vendors libwebp — on each vendor's own timeline. This is the step teams most often miss.
  3. Rebuild your own images and artifacts that embed libwebp. Safeguard's container security scanning surfaces a vulnerable libwebp deep inside a bundled runtime layer.
  4. Re-inventory to confirm; a patched host with an unpatched bundled app is the classic residual exposure.

How Safeguard surfaces and auto-fixes CVE-2023-4863

libwebp is the exact shape of dependency shallow tooling misses: a shared codec that appears many levels deep, often as a bundled or transitive node rather than a declared dependency. Safeguard walks resolved dependency graphs far deeper than typical SCA ceilings and captures the complete path to the vulnerable node, so a libwebp buried inside an Electron runtime or an image pipeline is still flagged. Vulnerability tracking ingests CISA KEV and EPSS alongside CVSS, so a bug confirmed as actively exploited — as this one was before its patch shipped — is elevated above the hundreds of lower-urgency CVEs in a typical backlog.

Where a version bump resolves it, automated fix pull requests propose the upgrade against your manifests and image definitions, and Griffin AI explains which of your artifacts carry a reachable, bundled copy versus an inert one. If you want to see how deep-graph resolution changes outcomes on vendored native libraries, our comparison against Snyk goes through it.

One decoding bug in a fifteen-year-old codec forced half the internet to rebuild. The durable defense is knowing, continuously, everywhere a library lives — not just where a manifest declares it.

Start at app.safeguard.sh/register, or read the docs at docs.safeguard.sh.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.