Back to Blog
high SEVERITY6 min read

How Denial of Service via excessive memory allocation happens in Node.js adm-zip and how to fix it

A high-severity Denial of Service vulnerability (CVE-2026-39244) was discovered in adm-zip version 0.5.16, allowing attackers to crash Node.js applications by sending specially crafted ZIP files that trigger excessive memory allocation. The fix involves upgrading to adm-zip 0.6.0, which implements proper bounds checking during ZIP file decompression.

O
By Orbis AppSec
Published July 27, 2026Reviewed July 27, 2026

Answer Summary

CVE-2026-39244 is a high-severity Denial of Service vulnerability in the Node.js adm-zip library (versions prior to 0.6.0) that allows attackers to crash applications by sending malformed ZIP files that cause excessive memory allocation. This is related to CWE-400 (Uncontrolled Resource Consumption). The fix requires upgrading adm-zip from 0.5.16 to 0.6.0 in your package.json, which adds proper validation of ZIP file headers before memory allocation.

Vulnerability at a Glance

cweCWE-400 (Uncontrolled Resource Consumption)
fixUpgrade adm-zip to version 0.6.0 which validates ZIP headers before allocation
riskRemote attackers can crash web services by uploading crafted ZIP files
languageNode.js (JavaScript)
root causeadm-zip 0.5.16 allocates memory based on untrusted ZIP header values without validation
vulnerabilityDenial of Service via excessive memory allocation

Introduction

In a web service using the whistle proxy tool, a high-severity vulnerability was discovered lurking in the package-lock.json file. The application depended on adm-zip version 0.5.16, a popular Node.js library for handling ZIP file operations. This dependency, used in production code paths that handle user-influenced input, contained CVE-2026-39244—a Denial of Service vulnerability that could allow remote attackers to crash the entire service with a single malicious ZIP file.

The vulnerability is particularly dangerous because this is a web service where request handlers are directly exposed to remote attackers. Any endpoint accepting ZIP file uploads or processing ZIP content becomes an attack vector.

The Vulnerability Explained

CVE-2026-39244 affects how adm-zip version 0.5.16 processes ZIP file headers during decompression. ZIP files contain metadata headers that declare the uncompressed size of contained files. In vulnerable versions, adm-zip trusts these header values without validation and allocates memory accordingly.

Here's the problematic dependency declaration that was in the codebase:

"dependencies": {
    "adm-zip": "0.5.16",
    ...
}

And in the lockfile:

"node_modules/adm-zip": {
    "version": "0.5.16",
    "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz",
    "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==",
    "engines": {
        "node": ">=12.0"
    }
}

How the Attack Works

An attacker can craft a malicious ZIP file with manipulated header values that claim an enormous uncompressed size (e.g., several gigabytes or more) while the actual compressed payload remains tiny. When the application processes this file:

  1. The attacker sends a small ZIP file (perhaps only a few kilobytes) to an endpoint that processes ZIP content
  2. adm-zip reads the malicious header claiming the file decompresses to, say, 8GB
  3. The library attempts to allocate 8GB of memory based on this untrusted value
  4. Node.js either crashes with an out-of-memory error or becomes unresponsive
  5. The web service goes down, affecting all users

This attack is particularly insidious because:
- The malicious file is small, bypassing typical upload size limits
- No actual decompression of large data occurs—the crash happens during memory allocation
- A single request can take down the entire service
- The attack requires no authentication if any public endpoint handles ZIP files

Real-World Impact

For this whistle proxy service, the impact is severe. As noted in the threat model context, this is a web service where vulnerabilities in request handlers are directly exploitable by remote attackers. An attacker could:

  • Cause complete service outage with minimal effort
  • Launch repeated attacks to prevent service recovery
  • Use this as a distraction while conducting other attacks
  • Impact all users relying on the proxy service

The Fix

The fix involves upgrading adm-zip from version 0.5.16 to 0.6.0, which implements proper validation of ZIP header values before allocating memory.

Changes to package.json

Before:

"dependencies": {
    "adm-zip": "0.5.16",

After:

"dependencies": {
    "adm-zip": "^0.6.0",

Changes to package-lock.json

Before:

"node_modules/adm-zip": {
    "version": "0.5.16",
    "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz",
    "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==",
    "engines": {
        "node": ">=12.0"
    }
}

After:

"node_modules/adm-zip": {
    "version": "0.6.0",
    "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.6.0.tgz",
    "integrity": "sha512-XleryMhbuksdKtofnWZ9Sk+4CUTbms4Mb/EU32SZwToAyZ5RgVos/ki8n+yr0LWHOGKuakbXTuuYNHLQjhddgg==",
    "license": "MIT",
    "engines": {
        "node": ">=14.0"
    }
}

Why This Fix Works

Version 0.6.0 of adm-zip introduces validation checks that:

  1. Verify ZIP header values against reasonable bounds before allocation
  2. Cross-reference declared sizes with actual compressed data ratios
  3. Implement safeguards against decompression bombs and memory exhaustion attacks

The version bump also updates the minimum Node.js requirement from 12.0 to 14.0, indicating the fix leverages newer Node.js APIs for safer memory handling.

Note the use of ^0.6.0 (caret version) in package.json, which allows automatic updates to future patch versions (0.6.x) while maintaining compatibility, ensuring the application receives future security fixes in this version range.

Prevention & Best Practices

Secure Dependency Management

  1. Regular dependency audits: Run npm audit regularly and integrate it into CI/CD pipelines
  2. Automated updates: Use tools like Dependabot or Renovate to receive automatic PRs for security updates
  3. Lock file hygiene: Always commit package-lock.json and review changes to dependency versions

Defensive Coding for File Processing

// Good: Implement additional safeguards even with patched libraries
const AdmZip = require('adm-zip');

function processZipSafely(buffer, maxSize = 100 * 1024 * 1024) {
    // Check input size first
    if (buffer.length > maxSize) {
        throw new Error('ZIP file exceeds maximum allowed size');
    }

    const zip = new AdmZip(buffer);
    const entries = zip.getEntries();

    // Validate total uncompressed size
    let totalSize = 0;
    for (const entry of entries) {
        totalSize += entry.header.size;
        if (totalSize > maxSize) {
            throw new Error('Uncompressed content exceeds maximum allowed size');
        }
    }

    return zip;
}

Resource Limits

  • Set Node.js memory limits: node --max-old-space-size=512 app.js
  • Implement request timeouts for file processing endpoints
  • Use process managers that restart crashed services automatically

Security Scanning Tools

  • Trivy: The scanner that detected this vulnerability
  • npm audit: Built-in Node.js security auditing
  • Snyk: Comprehensive dependency vulnerability scanning
  • OWASP Dependency-Check: Language-agnostic dependency analysis

Key Takeaways

  • adm-zip 0.5.16 trusts ZIP header values without validation, allowing attackers to trigger memory exhaustion with crafted files
  • Web services handling ZIP uploads are directly exploitable—this isn't a theoretical risk but an attack any remote user could execute
  • Small malicious files bypass upload limits—the attack payload can be just kilobytes while claiming to decompress to gigabytes
  • Dependency updates are security patches—the single-line change from 0.5.16 to ^0.6.0 eliminates this entire attack vector
  • Defense in depth matters—even with patched libraries, implement your own size validation and resource limits

How Orbis AppSec Detected This

  • Source: ZIP file data entering through web service request handlers
  • Sink: adm-zip library's memory allocation during ZIP processing in production code paths
  • Missing control: No validation of ZIP header size declarations before memory allocation in adm-zip 0.5.16
  • CWE: CWE-400 (Uncontrolled Resource Consumption)
  • Fix: Upgraded adm-zip from 0.5.16 to 0.6.0, which implements proper bounds checking on ZIP header values

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

CVE-2026-39244 demonstrates how a single vulnerable dependency can expose an entire web service to Denial of Service attacks. The adm-zip library's failure to validate ZIP header values before memory allocation created a situation where attackers could crash production services with minimal effort.

The fix—upgrading to adm-zip 0.6.0—is straightforward but highlights the importance of:
- Maintaining up-to-date dependencies
- Running automated security scans in CI/CD pipelines
- Understanding how third-party libraries handle untrusted input
- Implementing defense-in-depth with application-level resource limits

For developers working with file processing in Node.js, always assume uploaded files are malicious and implement multiple layers of validation beyond what your libraries provide.

References

Frequently Asked Questions

What is a memory exhaustion DoS vulnerability?

A memory exhaustion DoS occurs when an attacker can force an application to allocate excessive amounts of memory by providing malicious input, causing the application to crash or become unresponsive due to out-of-memory conditions.

How do you prevent memory exhaustion vulnerabilities in Node.js?

Validate and limit resource allocation based on untrusted input, set memory limits using Node.js flags like --max-old-space-size, implement timeouts for operations, and keep dependencies updated to versions that include proper bounds checking.

What CWE is memory exhaustion DoS?

CWE-400 (Uncontrolled Resource Consumption) covers vulnerabilities where an application doesn't properly restrict the amount of resources consumed, including memory exhaustion attacks.

Is input validation enough to prevent ZIP bomb attacks?

No, basic input validation like checking file extensions is insufficient. You need libraries that validate ZIP header metadata against actual content and implement decompression limits to prevent both traditional ZIP bombs and memory exhaustion attacks.

Can static analysis detect memory exhaustion vulnerabilities in dependencies?

Yes, tools like Trivy, Snyk, and npm audit can detect known CVEs in dependencies. However, they rely on vulnerability databases, so keeping tools updated and running scans regularly is essential for catching newly disclosed issues like CVE-2026-39244.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #1343

Related Articles

critical

How Server-Side Request Forgery (SSRF) happens in JavaScript fetch() and how to fix it

A critical Server-Side Request Forgery vulnerability in `popup.js` allowed attackers to inject malicious URLs from scraped webpages directly into fetch() calls, potentially accessing internal network resources and AWS metadata endpoints. The fix adds URL validation to ensure only HTTP/HTTPS protocols are used and blocks requests to private IP ranges and localhost addresses.

high

How NO_PROXY bypass via crafted URL happens in Node.js axios and how to fix it

A high-severity vulnerability (CVE-2026-42043) in axios versions prior to 1.15.1 allowed attackers to bypass NO_PROXY environment variable restrictions using specially crafted URLs. This meant HTTP requests intended to stay internal could be routed through an attacker-controlled proxy, potentially exposing sensitive data. The fix upgrades axios to version 1.15.1, which correctly validates URLs against NO_PROXY rules.

critical

How JSON request validation bypass happens in Node.js API handlers and how to fix it

A critical validation bypass in the `/api/agents/jobs` endpoint allowed attackers to send malformed JSON with arbitrary properties that could trigger prototype pollution or unexpected behavior. The fix added comprehensive validation checks including array detection and property existence verification to prevent malicious payloads from reaching downstream processing logic.

critical

How Server-Side Request Forgery happens in Node.js httpProxy.js and how to fix it

A critical Server-Side Request Forgery (SSRF) vulnerability was discovered in `hubcmdui/routes/httpProxy.js` where the `/proxy/test` endpoint passed a user-controlled `testUrl` parameter directly to `axios.get()` without any validation. An attacker could exploit this to probe internal infrastructure — including AWS metadata endpoints, Redis instances, and private network ranges. The fix introduces a strict URL validation function that blocks private IP ranges, loopback addresses, and non-HTTP(S)

critical

How Remote Configuration Injection happens in JavaScript fetch() and how to fix it

A critical vulnerability in `js/config.js` allowed attackers to inject malicious configuration data through DNS spoofing or man-in-the-middle attacks. The application fetched remote JSON configuration from GitHub without validating the response structure, enabling arbitrary code execution through crafted payloads. A single validation check now ensures only properly-formed configuration objects are accepted.

high

How missing Dependabot cooldown configuration happens in GitHub Actions and how to fix it

A high-severity vulnerability was discovered in the `.github/dependabot.yml` configuration file where no cooldown period was set for dependency updates. This exposed the Node.js library and its downstream consumers to potentially malicious or unstable packages immediately after publication. The fix adds a 7-day cooldown period to all package ecosystem entries, providing a critical safety buffer before accepting newly published package versions.