Injection

NestJS Injection Remediation Guide [Mar 2026] [CVE-2024-29409]

[Updated March 2026] Updated CVE-2024-29409

Overview

CVE-2024-29409 describes a file upload vulnerability in NestJS v10.3.2 (CWE-94) where an attacker could abuse the Content-Type header to trigger remote code execution on the server. This class of vulnerability arises when the server uses unvalidated headers to decide how to process uploaded content, potentially loading, evaluating, or executing code derived from user-provided data. In real-world deployments, such flaws can lead to full host compromise, data breach, or persistence in the environment if not properly mitigated. The risk is heightened in microservice architectures where file-handling endpoints are exposed and integrated with dynamic module loading, making attackers’ payloads harder to sandbox. This guide references CVE-2024-29409 to illustrate the concrete impact and the CWE-94 category it maps to.

Affected Versions

10.3.2

Code Fix Example

NestJS API Security Remediation
import { Controller, Post, Req, UseInterceptors, UploadedFile, BadRequestException } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';

@Controller('upload')
export class UploadController {
  // Vulnerable pattern (conceptual demonstration, do not deploy in production)
  @Post('vulnerable')
  @UseInterceptors(FileInterceptor('file'))
  async uploadVulnerable(@Req() req, @UploadedFile() file: Express.Multer.File) {
    const contentType = req.headers['content-type'] || '';
    // Insecure: decision based on Content-Type header
    if (contentType.includes('application/javascript')) {
      // Potential insecure path: uploaded JS payload could be loaded or evaluated
      // DO NOT enable eval or dynamic module loading from uploads in real code
      const code = file?.buffer?.toString('utf8') ?? '';
      // eslint-disable-next-line no-eval
      // eval(code); // This is intentionally disabled in this demo
    }
    return { message: 'vulnerable pattern received' };
  }

  // Secure fix: safe upload handling without relying on Content-Type for code execution
  @Post('secure')
  @UseInterceptors(FileInterceptor('file', {
    storage: diskStorage({
      destination: './uploads',
      filename: (req, file, cb) => {
        const safeName = Date.now() + '-' + file.originalname.replace(/[^a-z0-9.\-]/gi, '_');
        cb(null, safeName);
      }
    }),
    limits: { fileSize: 5 * 1024 * 1024 }, // 5 MB limit
    fileFilter: (req, file, cb) => {
      const allowed = ['image/png', 'image/jpeg', 'application/pdf', 'text/plain'];
      if (allowed.includes(file.mimetype)) {
        cb(null, true);
      } else {
        cb(new BadRequestException('Unsupported file type'), false);
      }
    }
  }))
  async uploadSecure(@UploadedFile() file: Express.Multer.File) {
    // Safe: file is saved to disk with a sanitized name; no code execution
    return { filename: file.filename, size: file.size };
  }
}

CVE References

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