DEV Community

Cover image for Level Up Your Website with Malware Detection ๐Ÿ”ฅ
Tommaso Bertocchi
Tommaso Bertocchi

Posted on

Level Up Your Website with Malware Detection ๐Ÿ”ฅ

Introduction

The majority of website have a form where files are been uploaded.

Hacker could easily insert a malicious file that will create backdoor.

In this article we are going to improve your React, NextJS and ExpressJS site to be able to protect against this exploits.

Let's get started! ๐Ÿƒ

๐Ÿค” What do we start with?

For our website, we will use a ready-made solution called pompelmi, a NPM package for detect easily if a file contains malware.

GitHub Repo Preview

1. Installation

Inside the root of your project type

npm install pompelmi
# or: yarn add pompelmi / pnpm add pompelmi
Enter fullscreen mode Exit fullscreen mode

And we installed all the need.

2.a โš›๏ธ React

For React:

import React, { useState, useCallback } from 'react';
import { createRemoteEngine } from 'pompelmi';

const YARA_RULES = `
rule demo_contains_virus_literal {
  strings:
    $a = "virus" ascii nocase
  condition:
    $a
}
`;  

export function FileScanner({ endpoint = 'http://localhost:8787/api/yara/scan' }) {
  const [result, setResult] = useState(null);

  const handleFile = useCallback(async (e) => {
    const file = e.target.files?.[0];
    if (!file) return;

    const engine = await createRemoteEngine({
      endpoint,
      mode: 'json-base64',
      rulesAsBase64: true,
    });
    const compiled = await engine.compile(YARA_RULES);

    const bytes = new Uint8Array(await file.arrayBuffer());
    const matches = await compiled.scan(bytes);

    setResult(matches);
  }, [endpoint]);

  return (
    <div>
      <input type="file" onChange={handleFile} />
      {result && (
        <pre style={{ whiteSpace: 'pre-wrap', marginTop: '1rem' }}>
          {JSON.stringify(result, null, 2)}
        </pre>
      )}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

2.3 ๐Ÿ‡ณ Next.JS

For NextJS:

// app/api/upload/route.ts
import { createNextUploadHandler } from '@pompelmi/next-upload';

export const runtime = 'nodejs';          // Next: Node runtime (not Edge)
export const dynamic = 'force-dynamic';   // optional: avoid route cache

const SimpleEicarScanner = { /* same as above */ };

export const POST = createNextUploadHandler({
  scanner: SimpleEicarScanner,
  includeExtensions: ['txt','png','jpg','jpeg','pdf','zip'],
  allowedMimeTypes: ['text/plain','image/png','image/jpeg','application/pdf','application/zip'],
  maxFileSizeBytes: 20 * 1024 * 1024,
  timeoutMs: 5000,
  concurrency: 4,
  failClosed: true,
  onScanEvent: (ev) => console.log('[scan]', ev)
});
}
Enter fullscreen mode Exit fullscreen mode

3.c โ˜• ExpressJS

For ExpressJS:

import express from 'express';
import multer from 'multer';
import { createUploadGuard } from '@pompelmi/express-middleware';

const app = express();
const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 20 * 1024 * 1024 } });

// Simple demo scanner (replace with YARA rules in production)
const SimpleEicarScanner = {
  async scan(bytes: Uint8Array) {
    const text = Buffer.from(bytes).toString('utf8');
    if (text.includes('EICAR-STANDARD-ANTIVIRUS-TEST-FILE')) return [{ rule: 'eicar_test' }];
    return [];
  }
};

app.post(
  '/upload',
  upload.any(),
  createUploadGuard({
    scanner: SimpleEicarScanner,
    includeExtensions: ['txt','png','jpg','jpeg','pdf','zip'],
    allowedMimeTypes: ['text/plain','image/png','image/jpeg','application/pdf','application/zip'],
    maxFileSizeBytes: 20 * 1024 * 1024,
    timeoutMs: 5000,
    concurrency: 4,
    failClosed: true,
    onScanEvent: (ev) => console.log('[scan]', ev)
  }),
  (req, res) => {
    res.json({ ok: true, scan: (req as any).pompelmi ?? null });
  }
);

app.listen(3000, () => console.log('demo on http://localhost:3000'));
Enter fullscreen mode Exit fullscreen mode

3 ๐Ÿš€ You're Ready!

All the things are done, now you malware detection integration is ready!

Repository: https://github.com/pompelmi/pompelmi

Warning โš ๏ธ: It's an Alpha, something will not work, the author takes no responsibility for any problems.

Disclosure: Iโ€™m the author.

Top comments (0)