Skip to content
Heist/ feed
Back to feed
MediumFix available

adm-zip: getDataAsync() bypasses the maxOutputLength size guard enforced by the synchronous getData() path

Type: advisorySources: OSV

### Summary adm-zip enforces a `maxOutputLength` guard against decompression bombs on its synchronous `getData()` path, but the equivalent asynchronous `getDataAsync()` path does not enforce it — it accumulates and returns the entire decompressed output regardless of the entry's declared size. An application that checks an entry's declared size before deciding to process it, then reads the entry via `getDataAsync()` (a completely ordinary, often-recommended choice for I/O in Node.js), gets none of the protection it believes it has. ### Details - `methods/inflater.js:3-10` passes `{maxOutputLength: expectedLength}` to `inflateRawSync`, which Node enforces. - `methods/inflater.js:12-31` passes the same option to `createInflateRaw` but never enforces it on the streaming path — it just accumulates every chunk and allocates a final Buffer of whatever size resulted. ### PoC ```js const AdmZip = require('adm-zip'); const zip = new AdmZip(); zip.addFile('p', Buffer.alloc(64 * 1024 * 1024, 0x41)); // 64 MiB const raw = Buffer.from(zip.toBuffer()); // patch the local + central declared uncompressed size to 1 byte raw.writeUInt32LE(1, localHeaderSizeOffset); raw.writeUInt32LE(1, centralHeaderSizeOffset); const entry = new AdmZip(raw).getEntry('p'); entry.getData(); // throws: ERR_BUFFER_TOO_LARGE: Cannot create a Buffer larger than 1 bytes entry.getDataAsync((data, error) => { ... }); // returns the full 67,108,864-byte buffer, error is undefined ``` ### Impact An application that valid

Products
adm-zip
Affected versions
Not specified
Fixed versions
0.6.1
CVEs
CVE-2026-114103
Confirmed fixed CVEs
Not specified
Updated in this feed
31 Oct 2026, 14:09 UTC · Revision 1

Source evidence

adm-zip: getDataAsync() bypasses the maxOutputLength size guard enforced by the synchronous getData() path

core-osv · Original source

Published 29 Sept 2026, 23:10 UTC

### Summary adm-zip enforces a `maxOutputLength` guard against decompression bombs on its synchronous `getData()` path, but the equivalent asynchronous `getDataAsync()` path does not enforce it — it accumulates and returns the entire decompressed output regardless of the entry's declared size. An application that checks an entry's declared size before deciding to process it, then reads the entry via `getDataAsync()` (a completely ordinary, often-recommended choice for I/O in Node.js), gets none of the protection it believes it has. ### Details - `methods/inflater.js:3-10` passes `{maxOutputLength: expectedLength}` to `inflateRawSync`, which Node enforces. - `methods/inflater.js:12-31` passes the same option to `createInflateRaw` but never enforces it on the streaming path — it just accumulates every chunk and allocates a final Buffer of whatever size resulted. ### PoC ```js const AdmZip = require('adm-zip'); const zip = new AdmZip(); zip.addFile('p', Buffer.alloc(64 * 1024 * 1024, 0x41)); // 64 MiB const raw = Buffer.from(zip.toBuffer()); // patch the local + central declared uncompressed size to 1 byte raw.writeUInt32LE(1, localHeaderSizeOffset); raw.writeUInt32LE(1, centralHeaderSizeOffset); const entry = new AdmZip(raw).getEntry('p'); entry.getData(); // throws: ERR_BUFFER_TOO_LARGE: Cannot create a Buffer larger than 1 bytes entry.getDataAsync((data, error) => { ... }); // returns the full 67,108,864-byte buffer, error is undefined ``` ### Impact An application that valid

osv:GHSA-c6fg-446q-cg94

adm-zip

Fixed versions: 0.6.1

Complete source record
{
  "id": "82b31f0df39d31cd5bef86f1cc4228b334cca1a1788412c27ebc660cde4a014f",
  "url": "https://osv.dev/vulnerability/GHSA-c6fg-446q-cg94",
  "method": "structured",
  "payload": {
    "kind": "advisory",
    "title": "adm-zip: getDataAsync() bypasses the maxOutputLength size guard enforced by the synchronous getData() path",
    "summary": "### Summary adm-zip enforces a `maxOutputLength` guard against decompression bombs on its synchronous `getData()` path, but the equivalent asynchronous `getDataAsync()` path does not enforce it — it accumulates and returns the entire decompressed output regardless of the entry's declared size. An application that checks an entry's declared size before deciding to process it, then reads the entry via `getDataAsync()` (a completely ordinary, often-recommended choice for I/O in Node.js), gets none of the protection it believes it has. ### Details - `methods/inflater.js:3-10` passes `{maxOutputLength: expectedLength}` to `inflateRawSync`, which Node enforces. - `methods/inflater.js:12-31` passes the same option to `createInflateRaw` but never enforces it on the streaming path — it just accumulates every chunk and allocates a final Buffer of whatever size resulted. ### PoC ```js const AdmZip = require('adm-zip'); const zip = new AdmZip(); zip.addFile('p', Buffer.alloc(64 * 1024 * 1024, 0x41)); // 64 MiB const raw = Buffer.from(zip.toBuffer()); // patch the local + central declared uncompressed size to 1 byte raw.writeUInt32LE(1, localHeaderSizeOffset); raw.writeUInt32LE(1, centralHeaderSizeOffset); const entry = new AdmZip(raw).getEntry('p'); entry.getData(); // throws: ERR_BUFFER_TOO_LARGE: Cannot create a Buffer larger than 1 bytes entry.getDataAsync((data, error) => { ... }); // returns the full 67,108,864-byte buffer, error is undefined ``` ### Impact An application that valid",
    "evidence": "osv:GHSA-c6fg-446q-cg94",
    "products": [
      {
        "name": {
          "value": "adm-zip",
          "evidence": "/affected/0/package/name"
        },
        "prerequisites": [],
        "fixed_versions": [
          {
            "value": "0.6.1",
            "evidence": "/affected/0/ranges"
          }
        ],
        "affected_versions": []
      }
    ],
    "severity": "medium",
    "structured": {
      "id": "GHSA-c6fg-446q-cg94",
      "aliases": [
        "CVE-2026-114103",
        "GHSA-c6fg-446q-cg94"
      ],
      "metrics": [
        {
          "type": "CVSS_V3",
          "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L"
        }
      ],
      "affected": [
        {
          "ranges": [
            {
              "type": "SEMVER",
              "events": [
                {
                  "introduced": "0"
                },
                {
                  "fixed": "0.6.1"
                }
              ]
            }
          ],
          "package": {
            "name": "adm-zip",
            "purl": "pkg:npm/adm-zip",
            "ecosystem": "npm"
          },
          "database_specific": {
            "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/09/GHSA-c6fg-446q-cg94/GHSA-c6fg-446q-cg94.json",
            "last_known_affected_version_range": "<= 0.6.0"
          }
        }
      ],
      "modified": "2026-10-21T10:57:29.375696244Z",
      "provider": "osv",
      "references": [
        "https://github.com/cthackers/adm-zip/security/advisories/GHSA-c6fg-446q-cg94",
        "https://github.com/cthackers/adm-zip/commit/491600683dacb6cb9fe0718a0eeb9cb5eb49afa6",
        "https://github.com/cthackers/adm-zip",
        "https://github.com/cthackers/adm-zip/releases/tag/v0.6.1"
      ],
      "provider_metadata": {
        "cwe_ids": [
          "CWE-400",
          "CWE-770"
        ],
        "severity": "MODERATE",
        "github_reviewed": true,
        "nvd_published_at": null,
        "github_reviewed_at": "2026-09-29T23:10:32Z"
      }
    },
    "related_cves": [
      {
        "value": "CVE-2026-114103",
        "evidence": "/aliases"
      }
    ],
    "security_relevant": true,
    "severity_evidence": "/severity/0/score"
  },
  "source_id": "core-osv",
  "document_id": 392990,
  "published_at": "2026-09-29T23:10:32+00:00"
}