# adm-zip: Decompression-bomb protection (fix for CVE-2026-39244) can be bypassed by declaring uncompressed size as 0

adm-zip's decompression-bomb cap is skipped when a ZIP entry declares uncompressed size 0, letting a tiny archive inflate to multi-GB memory and OOM the process.

- Payout: Research
- Severity: high
- Program: adm-zip
- Found by: dilipk5
- Disclosed: 2026-09-29
- CVE: CVE-2026-39244
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-rcw4-f5rp-g42v
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-rcw4-f5rp-g42v
- Tags: area:oss domain:oss impact:dos kind:research platform:ghsa sev:high tech:nodejs technique:incomplete-fix technique:source-review vuln:dos

**Target:** npm library ZIP entry inflater (methods/inflater.js)
**Root cause:** The CVE-2026-39244 fix only passes zlib's `maxOutputLength` when the attacker-controlled declared uncompressed size (`CENLEN`/`LOCLEN`) is > 0; declaring 0 yields `option = {}` and no cap, falling back to zlib's multi-GB internal default.
**Steps:**
1. Build a ZIP with one DEFLATE entry of highly redundant content (e.g. 4MB of a repeated byte, near the ~1032:1 ratio).
2. Patch both the local file header and central directory 4-byte little-endian uncompressed-size fields to `0`, leaving compressed bytes and CRC32 untouched (CRC still validates over real output).
3. Load with `new AdmZip(buffer)` and call `.getEntries()[0].getData()` (or readFile/readAsText/extractAllTo).
4. Observe full 4,194,304-byte buffer returned with no restriction; control with declared size 1024 throws `Cannot create a Buffer larger than N bytes`.
**How found:** Read the CVE-2026-39244 patch in methods/inflater.js and noticed the `expectedLength > 0` guard on `maxOutputLength`; hypothesized that a zero declared size skips the cap entirely, then A/B tested identical payloads differing only in the header field.
**Exploitation:** Attacker supplies a small (tens-of-MB) ZIP with declared size 0 to any upload handler, CI artifact extractor or attachment scanner using adm-zip; decompression allocates memory bounded only by zlib's internal default, causing multi-GB consumption and process crash/OOM.
**Insight:** When auditing a fix that derives a safety limit from an attacker-controlled header field, test the boundary values (0, negative, max) that make the guard falsy — a conditional cap is no cap.

