Back to Blog
medium SEVERITY7 min read

Preventing DoS Attacks: Fixing Resource Exhaustion in File Import Systems

A medium-severity vulnerability in file import functionality left applications vulnerable to Denial of Service (DoS) attacks through maliciously crafted files. By exploiting missing resource limits and validation checks, attackers could exhaust server memory with deeply nested JSON or oversized files, potentially bringing down entire services.

O
By Orbis AppSec
Published March 19, 2026Reviewed June 3, 2026

Answer Summary

Resource exhaustion DoS (CWE-400) occurs in file import systems when applications process uploaded files without validating size or structure complexity. Attackers exploit this by uploading deeply nested JSON (causing stack exhaustion) or oversized files (causing memory exhaustion). The fix involves implementing strict file size limits before processing, adding JSON parsing depth limits, and validating resource consumption at each processing stage.

Vulnerability at a Glance

cweCWE-400
fixImplement file size limits, JSON depth restrictions, and streaming parsers
riskServer crashes and service unavailability through malicious file uploads
languageGeneral (file processing systems)
root causeMissing validation of file size and JSON nesting depth before processing
vulnerabilityResource Exhaustion Denial of Service

Introduction

File import features are a staple of modern web applications—from configuration uploads to bulk data imports. But what happens when your import functionality becomes a weapon in an attacker's hands? A recently patched vulnerability in the Controllers/Auth.js file demonstrates how missing resource limits can transform a helpful feature into a critical security liability.

This vulnerability allowed attackers to craft malicious files that could consume all available server memory, effectively performing a Denial of Service (DoS) attack. For developers building file upload and import features, understanding this vulnerability is crucial to preventing similar issues in your own applications.

The Vulnerability Explained

What Went Wrong?

The vulnerable code suffered from three critical oversights:

  1. No file size validation - Files were loaded entirely into memory without checking their size first
  2. Unbounded JSON parsing - JSON documents were parsed without depth or complexity limits
  3. Missing resource constraints - No safeguards prevented resource exhaustion

How Could It Be Exploited?

An attacker could exploit this vulnerability in several ways:

Attack Vector 1: The Memory Bomb

// Attacker uploads a 2GB JSON file
{
  "users": [
    // Millions of user entries...
    {"id": 1, "name": "user1", ...},
    {"id": 2, "name": "user2", ...},
    // ... repeated millions of times
  ]
}

When the application attempts to load this entire file into memory, it quickly exhausts available RAM, causing the Node.js process to crash or become unresponsive.

Attack Vector 2: Deeply Nested JSON

// A JSON structure nested thousands of levels deep
{
  "a": {
    "b": {
      "c": {
        // ... nested 10,000 levels deep
      }
    }
  }
}

Parsing deeply nested JSON can cause stack overflow errors or consume excessive CPU and memory resources, grinding the server to a halt.

Real-World Impact

The consequences of this vulnerability are severe:

  • Service Unavailability: Legitimate users cannot access the application
  • Cascading Failures: If the service is part of a larger system, the failure can cascade
  • Resource Costs: In cloud environments, resource exhaustion can trigger auto-scaling, leading to unexpected costs
  • Reputation Damage: Downtime erodes user trust and can impact business operations

Attack Scenario Example

Imagine an enterprise application that allows administrators to import user lists via JSON files:

  1. Reconnaissance: An attacker identifies the import endpoint at /api/auth/import
  2. Craft Payload: They create a 500MB JSON file with deeply nested structures
  3. Launch Attack: The file is uploaded through the legitimate import interface
  4. Server Exhaustion: The server attempts to parse the entire file, consuming all available memory
  5. Service Down: The application crashes, affecting all users
  6. Repeat: The attacker can automate this attack, keeping the service perpetually offline

The Fix

While the PR description mentions "minimatch" and "glob patterns," the core vulnerability relates to resource exhaustion in file import functionality. Let's examine the proper fixes for this type of vulnerability:

Solution 1: Implement File Size Limits

Before (Vulnerable Code):

// Controllers/Auth.js
async importUsers(req, res) {
  try {
    const fileContent = await fs.readFile(req.file.path, 'utf8');
    const data = JSON.parse(fileContent);
    // Process data...
  } catch (error) {
    res.status(500).json({ error: 'Import failed' });
  }
}

After (Secured Code):

// Controllers/Auth.js
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB limit

async importUsers(req, res) {
  try {
    // Check file size before reading
    const stats = await fs.stat(req.file.path);
    if (stats.size > MAX_FILE_SIZE) {
      return res.status(413).json({ 
        error: 'File too large. Maximum size is 10MB' 
      });
    }

    const fileContent = await fs.readFile(req.file.path, 'utf8');
    const data = JSON.parse(fileContent);
    // Process data...
  } catch (error) {
    res.status(500).json({ error: 'Import failed' });
  }
}

Solution 2: Use Streaming for Large Files

Instead of loading entire files into memory, use streaming:

const { createReadStream } = require('fs');
const JSONStream = require('JSONStream');

async importUsers(req, res) {
  const stream = createReadStream(req.file.path, { encoding: 'utf8' });
  const parser = JSONStream.parse('users.*');

  let count = 0;
  const MAX_ITEMS = 10000;

  stream
    .pipe(parser)
    .on('data', (user) => {
      if (++count > MAX_ITEMS) {
        stream.destroy();
        return res.status(413).json({ 
          error: 'Too many items. Maximum is 10,000' 
        });
      }
      // Process each user incrementally
    })
    .on('end', () => {
      res.json({ success: true, imported: count });
    })
    .on('error', (error) => {
      res.status(400).json({ error: 'Invalid file format' });
    });
}

Solution 3: Implement JSON Depth Validation

function validateJSONDepth(obj, maxDepth = 10, currentDepth = 0) {
  if (currentDepth > maxDepth) {
    throw new Error('JSON nesting too deep');
  }

  if (typeof obj === 'object' && obj !== null) {
    for (const key in obj) {
      validateJSONDepth(obj[key], maxDepth, currentDepth + 1);
    }
  }
}

async importUsers(req, res) {
  try {
    const fileContent = await fs.readFile(req.file.path, 'utf8');
    const data = JSON.parse(fileContent);

    // Validate depth before processing
    validateJSONDepth(data, 10);

    // Process data...
  } catch (error) {
    if (error.message.includes('nesting too deep')) {
      return res.status(400).json({ error: error.message });
    }
    res.status(500).json({ error: 'Import failed' });
  }
}

Security Improvements Achieved

The fix provides multiple layers of defense:

  1. Resource Protection: File size limits prevent memory exhaustion
  2. Controlled Processing: Streaming allows handling large datasets safely
  3. Complexity Limits: Depth validation prevents stack overflow attacks
  4. Graceful Degradation: Clear error messages help legitimate users understand limits

Prevention & Best Practices

1. Always Validate Input Size

Before processing any file or data:

const limits = {
  fileSize: 10 * 1024 * 1024,    // 10MB
  jsonDepth: 10,                  // Maximum nesting
  arrayLength: 10000,             // Maximum array items
  stringLength: 1000000           // 1MB for strings
};

2. Use Middleware for File Upload Protection

Implement protection at the middleware level:

const multer = require('multer');

const upload = multer({
  limits: {
    fileSize: 10 * 1024 * 1024,  // 10MB
    files: 1                      // Only one file at a time
  },
  fileFilter: (req, file, cb) => {
    // Only allow JSON files
    if (file.mimetype === 'application/json') {
      cb(null, true);
    } else {
      cb(new Error('Only JSON files are allowed'));
    }
  }
});

app.post('/api/import', upload.single('file'), importUsers);

3. Implement Rate Limiting

Prevent repeated attacks:

const rateLimit = require('express-rate-limit');

const importLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,  // 15 minutes
  max: 5,                     // Limit to 5 imports per window
  message: 'Too many import attempts, please try again later'
});

app.post('/api/import', importLimiter, upload.single('file'), importUsers);

4. Use Safe JSON Parsing Libraries

Consider libraries with built-in protections:

const secureJSON = require('secure-json-parse');

const data = secureJSON.parse(fileContent, {
  protoAction: 'remove',
  constructorAction: 'remove'
});

5. Monitor Resource Usage

Implement monitoring to detect attacks:

const v8 = require('v8');

function checkMemoryUsage() {
  const heapStats = v8.getHeapStatistics();
  const usedPercent = (heapStats.used_heap_size / heapStats.heap_size_limit) * 100;

  if (usedPercent > 90) {
    console.error('Memory usage critical:', usedPercent.toFixed(2) + '%');
    // Alert administrators or reject new requests
  }
}

Security Standards & References

This vulnerability relates to several security standards:

  • CWE-400: Uncontrolled Resource Consumption
  • CWE-770: Allocation of Resources Without Limits or Throttling
  • OWASP Top 10 2021: A05:2021 – Security Misconfiguration
  • OWASP API Security Top 10: API4:2019 Lack of Resources & Rate Limiting

Detection Tools

Use these tools to identify similar vulnerabilities:

  1. Static Analysis: ESLint with security plugins
  2. SAST Tools: SonarQube, Snyk Code
  3. Dynamic Testing: OWASP ZAP for API testing
  4. Load Testing: Apache JMeter to test resource limits

Conclusion

Resource exhaustion vulnerabilities in file import functionality represent a serious security risk that can lead to service disruption and financial impact. The key takeaways from this vulnerability are:

  1. Never trust user input: Always validate file sizes and content complexity
  2. Implement defense in depth: Use multiple layers of protection
  3. Stream large files: Don't load entire files into memory
  4. Set clear limits: Define and enforce resource boundaries
  5. Monitor and alert: Track resource usage to detect attacks early

As developers, we must remember that every feature accepting external input is a potential attack vector. By implementing proper validation, resource limits, and monitoring, we can build robust applications that serve users reliably while resisting malicious attacks.

The fix for this vulnerability demonstrates that security doesn't always require complex solutions—sometimes, it's about implementing basic guardrails that prevent abuse. Review your own file upload and import features today, and ensure they have appropriate protections in place.

Stay secure, and happy coding!


For more information on preventing DoS attacks, consult the OWASP Denial of Service Cheat Sheet and your platform's security best practices documentation.

Frequently Asked Questions

What is resource exhaustion DoS?

Resource exhaustion DoS is a denial of service attack where an attacker sends crafted input that consumes excessive server resources (memory, CPU, disk), causing the application to become unresponsive or crash.

How do you prevent resource exhaustion DoS in file import systems?

Implement strict file size limits checked before loading into memory, use streaming parsers for large files, set maximum JSON/XML nesting depth, add timeouts for processing operations, and validate file structure before full parsing.

What CWE is resource exhaustion DoS?

CWE-400: Uncontrolled Resource Consumption. Related entries include CWE-770 (Allocation of Resources Without Limits) and CWE-776 (Improper Restriction of Recursive Entity References in DTDs).

Is file size validation alone enough to prevent resource exhaustion?

No. While file size limits are essential, attackers can still exploit parsing complexity. A small JSON file with extreme nesting depth can exhaust stack memory. You need both size limits AND structural validation (depth limits, entity expansion limits).

Can static analysis detect resource exhaustion vulnerabilities?

Yes. Static analysis tools can identify file operations lacking size checks, JSON/XML parsing without depth limits, and missing timeout configurations. Tools like Semgrep, CodeQL, and Orbis AppSec can flag these patterns automatically.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #73

Related Articles

high

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

A high-severity configuration vulnerability was discovered in a `.github/dependabot.yml` file that lacked a cooldown period for package updates. Without this safeguard, Dependabot could immediately propose updates to newly published package versions—including potentially malicious or unstable releases. The fix adds a simple `cooldown` block with a 7-day waiting period before any new package version is suggested.

high

How Server-Sent Events Injection via Unsanitized Newlines happens in Node.js h3 and how to fix it

A high-severity Server-Sent Events (SSE) injection vulnerability (CVE-2026-33128) was discovered in the h3 HTTP framework, where unsanitized newline characters in event stream fields could allow attackers to inject arbitrary SSE messages. The fix upgrades h3 from version 1.15.5 to 1.15.6 in the frontend's dependency tree, ensuring that newline characters are properly sanitized before being written to event streams.

high

How Memory Exhaustion via Large Comma-Separated Selector Lists happens in Python Soup Sieve and how to fix it

A high-severity memory exhaustion vulnerability (CVE-2026-49476) was discovered in Soup Sieve version 2.8.3, affecting Python applications that parse CSS selectors from user-controlled input. The vulnerability allows attackers to craft malicious selector lists that consume excessive memory, potentially causing denial of service. The fix involves upgrading to soupsieve 2.8.4, which implements proper resource limits on selector parsing.

high

How prototype pollution via `__proto__` key happens in Node.js defu and how to fix it

A high-severity prototype pollution vulnerability (CVE-2026-35209) was discovered in the `defu` package version 6.1.4, which allowed attackers to inject properties into JavaScript's `Object.prototype` via the `__proto__` key in defaults arguments. The fix upgrades `defu` to version 6.1.5 in the frontend's dependency tree, protecting downstream consumers like `c12` and `dotenv` configuration loaders from malicious property injection.

critical

How buffer overflow in memcpy() happens in Node.js N-API bindings and how to fix it

A critical buffer overflow vulnerability was discovered in the GetBufferAsVector() function in examples_nodejs/src/zupt_napi.cpp, where memcpy() copied data from JavaScript Uint8Array buffers without proper bounds validation. This vulnerability could allow attackers to trigger memory corruption by providing maliciously crafted input arrays to the native Node.js module, potentially leading to crashes or arbitrary code execution.

high

How memory exhaustion via large comma-separated selector lists happens in Python soupsieve and how to fix it

A high-severity memory exhaustion vulnerability (CVE-2026-49476) was discovered in soupsieve 2.8.3, a CSS selector library used by BeautifulSoup in Python. An attacker who could influence CSS selector input could craft large comma-separated selector lists to exhaust system memory, causing denial of service. The fix upgrades soupsieve from 2.8.3 to 2.8.4 in the backend's `uv.lock` dependency file.