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