Unrestricted Resource Consumption

Unrestricted Resource Consumption in Node.js (Express) [GHSA-xw6w-9jjh-p9cr]

[Updated March 2026] Updated GHSA-xw6w-9jjh-p9cr

Overview

Unrestricted Resource Consumption in production can cause memory exhaustion or CPU saturation, leading to denial of service and degraded user experience. Attackers may send oversized payloads or flood routes, causing the Node.js process to allocate memory or perform heavy work until resources are exhausted. In Express apps this vulnerability often arises when body parsing and request-data handling are unbounded. If you enable express.json() or express.urlencoded() without size limits and store request bodies in memory, a single huge payload or long-running requests can exhaust memory and block the event loop. Because JavaScript runs on a single thread, a flood of large requests or heavy processing can block the event loop and affect all clients. This class of vulnerability is common when accepting file uploads or arbitrary JSON bodies without bounds, and it can be exploited even on modest hardware if rate limits are missing or data is not streamed. Mitigations center on bounding input, avoiding unbounded in-memory growth, and applying streaming where possible. Implement size limits on parsers, use rate limiting, validate inputs, and prefer writing to storage instead of keeping data in memory. The accompanying code example demonstrates both vulnerable and fixed patterns.

Code Fix Example

Node.js (Express) API Security Remediation
/* Vulnerable version (no input size limits, in-memory growth) */
const express = require('express');
const app = express();
let memoryStore = [];
app.use(express.json());
app.post('/store', (req, res) => {
  // Unbounded growth: each request payload is kept in memory
  memoryStore.push(req.body);
  res.json({ stored: memoryStore.length });
});

/* Fixed version (limits, bounded storage, rate limiting) */
const express2 = require('express');
const rateLimit = require('express-rate-limit');
const appFixed = express2();
const MAX_ITEMS = 1000;
let boundedStore = [];
appFixed.use(express2.json({ limit: '100kb' }));
const limiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 100, standardHeaders: true });
appFixed.use(limiter);
appFixed.post('/store', (req, res) => {
  boundedStore.push(req.body);
  if (boundedStore.length > MAX_ITEMS) boundedStore.shift();
  res.json({ stored: boundedStore.length });
});
appFixed.listen(3001, () => console.log('Fixed server listening on port 3001'));

CVE References

Choose which optional cookies to allow. You can change this any time.