FileDummy Logo
FileDummy
File Security & Integrity

Scan Uploaded Files for Viruses: ClamAV + Node.js Integration

Integrate ClamAV antivirus scanning into your Node.js file upload pipeline. Protect your application from malicious uploads with real-world code examples using clamscan.

September 20, 202611 min read1,420 views
nodejssecurityclamavantivirusfile-upload

Permitting users to upload arbitrary documents and archives creates an acute security liability. ClamAV is an open-source antivirus engine capable of detecting viruses, trojans, malicious macros, and zip bombs in real-time.

ClamAV Deployment Architecture

The recommended production architecture runs clamd (the ClamAV daemon) as a standalone container or local Unix socket service, communicating with your Node.js application via TCP port 3310 or Unix IPC.

Code
[User Upload] --> [Node.js API Server] --(INSTREAM via TCP 3310)--> [ClamAV Daemon (clamd)]
                        |
                        +--> If Clean: Persist to S3/R2
                        +--> If Infected: Quarantine & Log Security Alert
Verified Test Asset.pdf

Download a verified clean 10MB PDF sample to test your ClamAV scanning daemon without false positives.

Download Clean 10MB PDF →

Integrating with Node.js via clamscan

Terminal
npm install clamscan
TypeScript
import NodeClam from 'clamscan';

let clamScanInstance: NodeClam | null = null;

async function getClamScanner(): Promise<NodeClam> {
  if (clamScanInstance) return clamScanInstance;

  clamScanInstance = await new NodeClam().init({
    clamdscan: {
      host: process.env.CLAMAV_HOST || '127.0.0.1',
      port: Number(process.env.CLAMAV_PORT) || 3310,
      timeout: 60000,
    },
    preference: 'clamdscan',
  });

  return clamScanInstance;
}

export async function scanUploadedBuffer(fileBuffer: Buffer): Promise<{ isInfected: boolean; viruses: string[] }> {
  const scanner = await getClamScanner();
  const { isInfected, viruses } = await scanner.scanBuffer(fileBuffer);

  if (isInfected) {
    console.warn('MALWARE DETECTED IN UPLOAD:', viruses);
  }

  return { isInfected, viruses };
}

Handling Scans Asynchronously

Scanning large files takes 1–5 seconds. For files over 50MB:

  1. Save the file with status PENDING_SCAN in object storage.
  2. Publish a scan event to a background job queue (e.g. BullMQ / AWS SQS).
  3. Update file status to ACTIVE or REJECTED once ClamAV completes its evaluation.
NDL

Nguyen Dai Long

Author

Backend Lead • Distributed Systems & Cloud Edge Architecture Specialist

4+ years designing high-throughput file ingestion pipelines, database architectures, and distributed edge storage on Cloudflare R2 & AWS S3. Founder of FileDummy and the NDL Ecosystem.

Was this article helpful?

Click Like to support the author and help other developers discover this guide.

Engineering Discussion & Feedback (0)

Share benchmark results, report edge cases, or ask technical questions.

0/3000

No comments yet. Be the first developer to start the discussion!

Frequently Asked Questions

Is ClamAV good enough for production use?â–¾

ClamAV is adequate for common malware and macro-based threats. For enterprise-grade protection, combine with a commercial engine (VirusTotal API, OPSWAT) for multi-engine scanning. ClamAV's signature database updates multiple times daily via freshclam.

How slow does ClamAV make the upload process?â–¾

ClamAV scans at roughly 5–10MB per second per CPU core. A 10MB file takes 1–2 seconds. For large files, run the scan asynchronously and delay file access until the scan completes.

What is a zip bomb and does ClamAV detect it?â–¾

A zip bomb is a tiny archive that expands to a massive size (42KB → 4.5PB), designed to exhaust memory or disk. ClamAV detects known zip bomb patterns. Always set maxFileSize and maxScanSize limits in clamd.conf.

Related Articles