Skip to content

Secure file uploads in NestJS

This is the shortest NestJS path when you want upload scanning to fit into modules, interceptors, and controller decorators.

For the broader upload-boundary model that this controller flow fits into, see Secure file uploads in Node.js: Beyond Extension and MIME Checks.

Terminal window
npm install pompelmi @pompelmi/nestjs

If you use FileInterceptor() as shown below, make sure your Nest app also has @nestjs/platform-express and multer.

app.module.ts
import { Module } from '@nestjs/common';
import { PompelmiModule } from '@pompelmi/nestjs';
import {
CommonHeuristicsScanner,
composeScanners,
createZipBombGuard,
} from 'pompelmi';
const scanner = composeScanners(
[
['zipGuard', createZipBombGuard()],
['heuristics', CommonHeuristicsScanner],
],
{ stopOn: 'suspicious' }
);
@Module({
imports: [PompelmiModule.forRoot({ scanner })],
})
export class AppModule {}
import { Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { PompelmiInterceptor } from '@pompelmi/nestjs';
import { memoryStorage } from 'multer';
@Controller('upload')
export class UploadController {
@Post()
@UseInterceptors(
FileInterceptor('file', {
storage: memoryStorage(),
limits: { fileSize: 10 * 1024 * 1024 },
}),
PompelmiInterceptor
)
async upload(@UploadedFile() file: Express.Multer.File) {
return { ok: true, file: file.originalname };
}
}
  • PompelmiInterceptor requires memoryStorage() so the bytes are available before persistence.
  • The current interceptor blocks malicious uploads and logs suspicious ones. If you want custom quarantine behavior for suspicious, inject PompelmiService and handle the PompelmiScanReport directly.
  • Keep object storage or database writes outside the interceptor path until you have the verdict you want.