
Security Researcher
Heitor Gouvêa

Introduction
Syft is an open-source CLI tool and Go library, developed by Anchore, that generates a Software Bill of Materials (SBOM) from container images and filesystems. Think of it as a tool that produces a detailed "ingredient list" of everything inside your software. An SBOM is a formal, structured list of all the components, libraries, and packages that make up a piece of software, including their versions and licenses. It's essentially an inventory of your software's dependencies. When you point Syft at a container image (like a Docker image) or a directory, it scans it and identifies every package and library present. It can then output that inventory in a variety of standardized formats so other tools can consume it.
Its broad adoption speaks for itself: Docker, Grafana, Cilium, Helm, OpenTelemetry, Bitwarden, and hundreds of other major open-source projects rely on it, and it has been embedded as a library inside tools like Kubescape, ThreatMapper, and GoReleaser. With software supply chain security becoming a regulatory and industry priority, Syft fills a critical role by making it practical to know exactly what's inside your software.
Vulnerability
Syft's file: source handler contains a decompression bomb vulnerability in the way it processes compressed archives. When Syft is pointed at a compressed file, it extracts the entire contents to a temporary directory before scanning, and it does so without enforcing any limit on how large the extracted output can be. A carefully crafted archive can therefore be tiny on disk but expand to an enormous size during extraction, consuming all available disk space, saturating I/O, and ultimately crashing or hanging the system. The core issue lives in syft/source/filesource/file_source.go, inside the unarchiveToTmp function (around lines 260–292). At line 282, a bare io.Copy() call streams the decompressed content directly to disk with no size check, no threshold, and no early exit:

This single unbounded copy is all it takes. An attacker can construct a decompression bomb — a file where the compression ratio is extreme, such as one megabyte of compressed data expanding to hundreds of gigabytes of output and Syft will faithfully extract every byte of it.
Attack vector
The vulnerability is reachable through any code path that causes Syft to process an attacker-influenced archive via the file: scheme. The most direct route is simply invoking syft scan file:/path/to/malicious.tar.gz on a file the attacker controls, but in practice the more dangerous scenarios are those where Syft operates autonomously.
In CI/CD pipelines, it is common to scan pull request artifacts, freshly built container images, or incoming dependency packages automatically; an attacker who can introduce a malicious archive into that pipeline triggers the vulnerability without any further human interaction.
Similarly, package registries and software supply chains represent a high-value vector: a malicious package published to a public or internal registry can cause every downstream Syft scan of that package to detonate the bomb. Finally, any web application or API that accepts user-uploaded archives and passes them to Syft for scanning is directly exploitable by any user with upload access.
The attack flow itself is straightforward. Syft's fileAnalysisPath() detects that the input is a recognized archive format and hands it off to unarchiveToTmp(), which begins streaming decompressed bytes to $TMPDIR via the unbounded io.Copy(). There is no checkpoint, no quota and no watchdog, the extraction simply continues until either the archive is fully consumed or the filesystem runs out of space, at which point the host system is degraded or unresponsive.
Inconsistent security implementation
What makes this vulnerability particularly striking is that the Syft codebase already contains a purpose-built defense against decompression bombs, it simply isn't applied everywhere. In internal/file/copy.go, the developers defined a safeCopy() function that wraps io.Copy() with an io.LimitReader, capping the amount of data that can be extracted from any single file at two gigabytes. If that limit is reached, the function returns an explicit error identifying the event as a potential decompression bomb attack:

This function is used correctly in the internal file traversal paths. Both internal/file/tar_file_traversal.go and internal/file/zip_file_traversal.go call safeCopy() when reading archive entries, meaning those code paths are protected against exactly this class of attack.
The problem is that the file: source handler in syft/source/filesource/file_source.go bypasses this protection entirely, using a raw io.Copy() instead. The fix already exists in the repository, it just was not consistently applied. This is not a case of an unknown attack class or a missing mitigation strategy; the developers clearly understood the risk and built a solution for it. The vulnerable code path simply never received the same treatment, leaving a gap where the established pattern was not followed.

Newsletter Quor
Proof of concept
To demonstrate the vulnerability, we can construct a decompression bomb using nothing more than standard Unix utilities and a copy of Syft built from source. The principle is simple: a file consisting entirely of null bytes compresses extremely well, producing a ratio that makes even modest bombs practical to transmit or store while still capable of inflicting serious resource exhaustion on the target system. First, prepare the workspace and generate the malicious archive:

The dd command produces 200MB of zero bytes, and tar with gzip compression reduces this to roughly 200KB, a compression ratio of around 1000:1. In a real attack, this scales trivially; a 10MB archive of null bytes can expand to over 10GB, and an attacker is not limited to zero bytes or a single file entry. With the bomb prepared, note the available disk space and then point Syft at the archive:

On an unpatched build, Syft will create a temporary directory under $TMPDIR named syft-archive-contents-* and extract the full 200MB payload into it with no interruption. Watching du on that directory while the scan runs makes the problem immediately visible: the extracted size climbs steadily until extraction completes or the filesystem runs out of space. Scaling the dd count upward to produce a 10GB or larger payload will reliably exhaust disk space on most developer machines and CI runners, leaving the system degraded and potentially requiring manual cleanup of the temporary directory.
After applying the fix, replacing the bare io.Copy() call in unarchiveToTmp with the existing safeCopy() function, the behavior changes entirely. Extraction halts as soon as the per-file read limit of 2GB is reached, and Syft returns an error explicitly identifying the event as a potential decompression bomb attack. The temporary directory is still created, but its contents are bounded, and system resources are never meaningfully threatened.
Impact
The direct consequence of exploitation is denial of service against the host running Syft. A filled filesystem doesn't just stop Syft, it causes other processes writing to the same partition to fail, and recovery requires manually locating and deleting the extracted temporary directory Syft leaves behind.
The severity scales with deployment context. On a developer's machine the impact is disruptive but contained. In CI/CD pipelines it's more serious: shared runners with fixed disk quotas can have all concurrent jobs knocked out by a single malicious archive. The supply chain scenario is the most pointed, Syft is routinely used to scan incoming packages automatically, often before any human reviews them. An attacker who publishes a decompression bomb to a public or internal registry can cause every downstream Syft-based pipeline that scans it to exhaust its disk. A tool built to surface supply chain risk becomes a supply chain liability.
This vulnerability does not offer code execution, privilege escalation, or data exfiltration. Exploitation also requires the attacker to influence what archive Syft scans. In practice, that bar is low in the automated, trust-before-verify pipelines where Syft is most commonly deployed but it is worth stating clearly that the impact is denial of service, nothing more.
Recommendation
Users should upgrade to a patched release of Syft as soon as possible. f you are consuming Syft as a Go library rather than a CLI tool, ensure your go.mod is pinned to the patched version.
Conclusion
This vulnerability is a straightforward case of an incomplete security implementation. Syft's developers understood the decompression bomb threat, they wrote safeCopy(), documented it clearly, and applied it correctly in the internal traversal paths. The file: source handler was simply never brought in line with that established pattern, leaving a meaningful gap in a tool that is increasingly deployed in high-trust, automated environments.
For security tooling in particular, consistency matters. The whole point of a scanner like Syft is to be a trusted intermediary between untrusted software and the rest of your infrastructure. A vulnerability that can be triggered by the very artifacts Syft is asked to inspect undermines that trust in a direct way. The good news is that the remediation is minimal and the underlying design is sound, this is a one-line fix, not a structural problem.
Time line
Discovered and reported: 13/02/2026
Vulnerability confirmed by Anchor team: 19/02/2026
Fixed: 19/03/2026
Article published: 20/03/2026
References
Com o Quor, segurança vira vantagem competitiva. Descubra como em uma demo personalizada.