Skip to content

Secure file uploads in Koa

Koa leaves upload policy to your middleware stack. Pompelmi fits that model well: parse the file into memory, run the upload guard, and store only after the verdict is acceptable.

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

Terminal window
npm install pompelmi @pompelmi/koa-middleware koa @koa/router @koa/multer
import Koa from 'koa';
import Router from '@koa/router';
import multer from '@koa/multer';
import { createUploadGuard } from '@pompelmi/koa-middleware';
import {
CommonHeuristicsScanner,
composeScanners,
createZipBombGuard,
} from 'pompelmi';
const app = new Koa();
const router = new Router();
const scanner = composeScanners(
[
['zipGuard', createZipBombGuard()],
['heuristics', CommonHeuristicsScanner],
],
{ stopOn: 'suspicious' }
);
const upload = multer({
storage: multer.memoryStorage(),
limits: { fileSize: 10 * 1024 * 1024 },
});
router.post(
'/upload',
upload.single('file'),
createUploadGuard({
scanner,
includeExtensions: ['pdf', 'png', 'jpg', 'jpeg', 'zip'],
allowedMimeTypes: [
'application/pdf',
'image/png',
'image/jpeg',
'application/zip',
],
maxFileSizeBytes: 10 * 1024 * 1024,
failClosed: true,
}),
(ctx) => {
ctx.body = { ok: true, scan: (ctx.state as any).pompelmi };
}
);
app.use(router.routes()).use(router.allowedMethods());
  • It keeps Koa minimal while still giving you a real upload-security boundary.
  • It attaches the verdict to ctx.state.pompelmi, which is easy to pass into audit, quarantine, or storage code.
  • It works well when you want route-specific policies instead of a larger framework abstraction.