Jul 16, 2026·7 min read·4 visits
Uncontrolled file extraction in adawolfa/isdoc allows remote attackers to cause denial of service via zip decompression bombs or directory traversal.
A high-severity vulnerability exists in the adawolfa/isdoc PHP library before versions 1.4.1 and 2.0.0. The library fails to restrict or validate the sizes of files extracted from untrusted Zip archives (.isdocx container files) or PDF embedded streams. This allows remote attackers to perform decompression bomb attacks, causing denial of service via memory or disk exhaustion.
adawolfa/isdoc is a PHP library for reading and writing electronic invoices in the Slovak/Czech ISDOC format. This format supports multi-document packages (.isdocx) which are ZIP archives containing the primary XML invoice alongside embedded attachments, such as PDFs or images. Because these attachments are packed in a compressed ZIP container, the library must unpack them to process or store the invoice data.
Prior to security updates, the library did not validate the uncompressed size of ZIP entries before attempting to decompress them. This flaw exposes applications using the library to Uncontrolled Resource Consumption (CWE-409), commonly known as a decompression bomb or ZIP bomb. An attacker can craft a highly compressed ZIP entry that expands to hundreds of megabytes or gigabytes, leading to memory or disk exhaustion.
This vulnerability is tracked under the identifier GHSA-XG43-5579-QW6V. Since ISDOC documents are typically processed on backend servers handling financial transactions, successful exploitation results in a Denial of Service (DoS) for the processing system, disrupting invoice workflows and potentially crashing co-located services. The attack surface is highly accessible because electronic invoices are commonly uploaded by unauthenticated users or external suppliers.
The primary flaw resides in the handling of compressed streams within the .isdocx container files. When the library processes a document package, it utilizes PHP's native ZipArchive class to extract components. Specifically, calling $zip->getFromName($name) on a compressed stream forces the engine to expand the data fully into memory. If the entry is a decompression bomb, the expansion immediately exhausts the PHP memory_limit, terminating the process.
Additionally, the library's saveTo() method for remote supplements did not monitor stream byte consumption during execution. A secondary attack path allowed an attacker to declare a small size in metadata while delivering a stream of near-infinite length. This causes the application to write data until the server storage is completely filled, leading to persistent system-wide instability.
Furthermore, the parser lacks validation on XML External Entity (XXE) configurations during manifest parsing. If an application enables entity substitution or external DTD loading, the library becomes susceptible to XML Entity Expansion and local file disclosure. Finally, the default handling of supplement filenames lacked sanitization, creating a path traversal vulnerability where malicious filenames could overwrite arbitrary files on the local filesystem.
The vendor resolved these vulnerabilities by introducing central directory inspections and byte-budget stream copies. The following diagram illustrates how the patched parser inspects ZIP entries before and during extraction.
The diagram highlights the dual-layer validation model designed to catch both static size anomalies and dynamic stream inflation overflows.
To prevent decompression bombs, the library now implements the Adawolfa\ISDOC\X\Zip helper class. This class reads the ZIP's central directory metadata using ZipArchive::statName(), which contains the expected uncompressed size, before allocating any memory for the decompressed content:
final class Zip
{
public static function entrySize(ZipArchive $zip, string $name): ?int
{
$stat = $zip->statName($name);
return $stat === false ? null : $stat['size'];
}
}The XML extraction routines query this helper to enforce a maximum limit of 256 KB on standard invoice documents.
When writing supplements to disk, the patched saveTo() function enforces a strict running byte-limit within a fread loop. If the written bytes exceed the allowed limit, the process throws a SupplementException and deletes the partial file:
$written = 0;
$complete = false;
try {
while (!feof($resource)) {
$chunk = @fread($resource, 1 << 14);
if ($chunk === false) {
throw SupplementException::couldNotWriteFile($this->filename, $filename);
}
$written += strlen($chunk);
if ($sizeLimit !== null && $written > $sizeLimit) {
throw SupplementException::supplementTooLarge($this->filename, $written, $sizeLimit);
}
if (@fwrite($handle, $chunk) === false) {
throw SupplementException::couldNotWriteFile($this->filename, $filename);
}
}
$complete = true;
} finally {
fclose($handle);
if (!$complete) {
@unlink($filename);
}
}This dynamic tracking protects the file system against truncated or corrupt ZIP streams that attempt to bypass the static metadata checks.
Exploitation of GHSA-XG43-5579-QW6V does not require authentication and can be performed remotely if the target application exposes an upload form or an API endpoint for processing ISDOC invoices. The attacker constructs a malicious .isdocx file, which is a standard ZIP archive. Inside this archive, the attacker includes a file that compresses highly, such as an XML document containing recurring patterns of spaces or repeating characters.
A single kilobyte of compressed data can expand to multiple gigabytes of uncompressed content. When the target application receives and attempts to parse this file, the adawolfa/isdoc library calls $zip->getFromName(). This action forces PHP to allocate memory for the fully decompressed stream. Because the allocated memory exceeds the PHP memory_limit, the script crashes immediately, causing a denial of service.
In scenarios where the library processes PDF supplements, the attacker can leverage PDF-embedded streams compressed using the /FlateDecode filter. When the library parses the PDF to compute its integrity hash, the underlying parser decompresses the stream. This achieves the same outcome, consuming system memory until the PHP process terminates.
An analysis of the applied patches reveals potential bypass vectors that security teams must consider. In Supplement.php, the library uses the @filesize($this->path) function to validate file bounds before reading. In PHP, filesize() returns false when queried against remote stream wrappers such as http:// or ftp://. Because the size verification skips checks when filesize() returns false, remote stream supplements bypass the pre-flight size checks entirely.
Furthermore, when parsing PDF documents, the library computes a SHA1 integrity hash by calling $object->getContent(). This operation decompresses the stream to compute the hash before enforcing the post-extraction size checks in getContents(). Consequently, a PDF decompression bomb will still exhaust the server's memory and trigger a crash during the hash generation phase.
Finally, the declaresDoctype() helper uses a single-byte string comparison to detect <!DOCTYPE headers, protecting against XML External Entity attacks. However, libxml2 supports multi-byte document encodings like UTF-16BE or UTF-16LE. An attacker can encode the XML document in UTF-16BE, causing declaresDoctype() to miss the <!DOCTYPE pattern while libxml2 successfully decodes and processes the external entity declaration, leading to XXE injection.
To fully mitigate these vulnerabilities, developers must update adawolfa/isdoc to a patched version. For applications running the 1.4.x branch, upgrade to version 1.4.1. For applications running the 2.x branch, upgrade to version 2.0.0. These releases contain the necessary central directory checks and byte-budget stream processing rules.
If upgrading is not immediately possible, implement strict PHP resource limits in php.ini. Setting a reasonable memory_limit (e.g., 128M or 256M) ensures that memory-exhaustion attacks crash only the single PHP worker process rather than destabilizing the entire host operating system. Additionally, restrict file upload sizes at the web server layer (e.g., Nginx client_max_body_size or Apache LimitRequestBody) to prevent the submission of excessively large archives.
Furthermore, secure the extraction directory paths by sanitizing all incoming supplement filenames. Wrap filenames in basename() before using them in file operations to prevent path traversal attacks. When working with older PHP versions (prior to PHP 8.0), explicitly disable external entity loading globally using libxml_disable_entity_loader(true) to mitigate latent XML injection risks.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
adawolfa/isdoc adawolfa | < 1.4.1 | 1.4.1 |
adawolfa/isdoc adawolfa | >= 2.0.0-alpha, < 2.0.0 | 2.0.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-409 (Improper Handling of Highly Compressed Data) |
| Attack Vector | Network (Remote) |
| CVSS Score | 7.5 (High) |
| EPSS Score | 0.01 |
| Impact | Denial of Service (Memory/Disk Exhaustion) |
| Exploit Status | Proof-of-Concept Available |
| KEV Status | Not Listed |
The product does not sufficiently handle highly compressed data, such as ZIP bombs, which can exhaust system resources when decompressed.
A Denial of Service (DoS) vulnerability in the Rust crate `serde_with` arises from an integer underflow and uncontrolled memory allocation during the processing of empty collections using the `KeyValueMap` helper. Depending on the build profile, this flaw leads to an immediate thread panic (debug) or process abort due to an out-of-memory condition (release).
A critical remote code execution vulnerability exists in django-haystack prior to version 3.4.0. The vulnerability stems from the Elasticsearch 1.x search backend incorrectly processing aliased search result fields, leading to the unsafe execution of user-supplied strings using Python's built-in eval() function.
The obsidian-local-rest-api plugin prior to version 4.1.3 is vulnerable to an authenticated path traversal flaw in its /vault/{path} endpoints. An authenticated attacker can bypass the vault root boundary using URL-encoded directory traversal sequences to perform unauthorized operations on the host filesystem.
An authenticated Server-Side Request Forgery (SSRF) vulnerability in Koel, an open-source personal music streaming server, allows remote attackers to probe internal hosts and loopback addresses. The vulnerability arises due to a missing 'bail' validation rule in the Laravel-based form validation pipeline, which permits downstream HTTP checks to execute even after a URL has failed security verification.
A Server-Side Request Forgery (SSRF) vulnerability in the open-source personal music streaming server Koel allows authenticated Subsonic API users to perform unauthorized network queries. This flaw resides in both the Subsonic podcast feed import routine and the subsequent redirect handling inside the podcast streaming helper, exposing private local networks and internal loopback systems to unauthorized reconnaissance and interaction.
CVE-2026-50661 is a security feature bypass vulnerability in Microsoft Windows BitLocker full-disk encryption. A physical attacker can exploit this flaw to bypass encryption controls, permitting unauthorized access to sensitive local storage and the modification of offline system configurations.