Unrestricted Resource Consumption

Unrestricted Resource Consumption in Node.js (Express) [GHSA-c875-h985-hvrc]

[Updated March 2026] Updated GHSA-c875-h985-hvrc

Overview

Remediation guidance for Unrestricted Resource Consumption vulnerabilities in Node.js (Express). No CVEs provided here; this guide explains real-world impact and how this vulnerability can manifest in typical Express apps, with practical mitigations. Attackers can exploit unbounded request processing or CPU-bound tasks to exhaust memory or CPU resources, leading to slowdowns or outages for legitimate users. By failing to bound inputs, body parsing, and synchronous work, an Express service can become a vector for Denial of Service (DoS) without the attacker needing to breach authentication or gain privileged access. Understanding how this class of vulnerability appears in Node.js/Express environments helps developers implement robust guards against resource exhaustion. In real-world deployments, this vulnerability often arises when endpoints read large payloads entirely into memory, or perform heavy, synchronous computations on user-provided data within the request handler or middleware stack. Express middleware like body parsers (express.json, express.urlencoded) can amplify risk if their limits are too lax or absent. Likewise, CPU-intensive processing in route handlers or utilities running in the event loop blocks other requests, allowing a single request to degrade service quality or shut down the process under memory pressure. The impact can be severe in services handling file uploads, data transformation, or real-time request-driven workloads. The patterns described here are common across Node.js/Express apps and should be addressed with a layered approach: bound input sizes, offload CPU work, constrain concurrency, and monitor for abuse. The following code snippet demonstrates a vulnerable pattern and a fixed approach side by side, illustrating how proper limits and worker-based execution can mitigate risk while preserving functionality.

Code Fix Example

Node.js (Express) API Security Remediation
/* Vulnerable pattern (unbounded body parsing + CPU-bound work in event loop) */
const express = require('express');
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');

if (isMainThread) {
  const app = express();
  // No limit on request body size; this can allow large payloads to be buffered in memory
  app.use(express.json());
  app.post('/process', async (req, res) => {
    const data = req.body.data;
    // CPU-intensive work runs in the main event loop
    let result = 0;
    for (let i = 0; i < data.length * 1000; i++) {
      result += Math.sqrt(i) * Math.sin(i);
    }
    res.json({ result });
  });
  app.listen(3000, () => console.log('listening on 3000'));
}

/* Fixed pattern (limits + offloaded CPU work to worker thread) */
if (isMainThread) {
  // Start server with input size limit
  const app = express();
  app.use(express.json({ limit: '1mb' })); // bound payload size
  app.post('/process', async (req, res) => {
    const data = req.body.data;
    const result = await runHeavyTask(data);
    res.json({ result });
  });
  app.listen(3001, () => console.log('listening on 3001'));

  function runHeavyTask(data) {
    return new Promise((resolve, reject) => {
      const worker = new Worker(__filename, { workerData: data });
      worker.on('message', resolve);
      worker.on('error', reject);
      worker.on('exit', (code) => {
        if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`));
      });
    });
  }
} else {
  // Worker thread performs CPU-intensive work off the main event loop
  const data = workerData;
  let result = 0;
  for (let i = 0; i < data.length * 1000; i++) {
    result += Math.sqrt(i) * Math.sin(i);
  }
  parentPort.postMessage(result);
}

CVE References

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