Securing File Uploads in Frappe with Virus Scanning using ClamAV and PyClamd

 · 2 min read

In today's digital world, securing file uploads is not just good practice—it's essential. While Frappe/ERPNext offers a robust platform for web applications and ERP systems, it doesn't scan uploaded files for malware or viruses by default.

To strengthen our application's security, we’ve integrated ClamAV—an open-source antivirus engine with Frappe using the pyclamd Python library. This setup ensures that every uploaded file is scanned before it's saved, helping protect our software and our users.

🔧 Why Virus Scanning?

Allowing users to upload files without checking for malware creates a significant risk. Malicious files can:

  • Exploit vulnerabilities in the system.
  • Be downloaded by other users, causing data breaches.
  • Get synced with other systems, spreading the threat further.

Adding a virus scanning layer ensures only clean files are accepted.

⚙️ Step-by-Step Setup

1. Install Required Packages

source env/bin/activate
pip3 install pyclamd
sudo apt-get install clamav clamav-daemon -y

2. Configure ClamAV Daemon

Edit the ClamAV config file:

sudo nano /etc/clamav/clamd.conf
Uncomment or add the following:
TCPSocket 3310
TCPAddr 127.0.0.1

Then restart the daemon:

sudo systemctl restart clamav-daemon

You can verify the daemon is running:

sudo systemctl status clamav-daemon
sudo lsof -i :3310

⚠️ Note: For development environments, you might use chmod 666 /var/run/clamav/clamd.ctl, but this is not recommended for production. Configure proper permissions instead.

🧩 Integrating with Frappe

We use the before_insert hook on the File doctype to scan every file before it's saved.

1. Add Hook in hooks.py


doc_events = {
    "File": {
        "before_insert": "yourapp.path.to.file.scan_file_for_virus"
    }
}

2. Add Virus Scan Code (file.py)

📄 Python Code to Scan Uploaded Files for Viruses



import pyclamd
from frappe import _
import frappe
import os

def scan_file_for_virus(doc, method):
    if "private/" in str(doc.file_url):
        file_path = frappe.get_site_path(doc.file_url.strip("/"))
    else:
        file_path = frappe.get_site_path(doc.file_url.strip("/"))

    full_path = os.path.abspath(file_path)
    cd = pyclamd.ClamdNetworkSocket()
    if cd.ping():
        result = cd.scan_file(full_path)
        if result:
            frappe.throw(_("Virus detected in uploaded file! Upload aborted."))

✅ Benefits of This Integration

  • Prevents malicious uploads that could compromise your system or your users.
  • Works seamlessly with Frappe's file system.
  • Easily extendable to scan files in background jobs or workflows.

📬 Let's Connect

Got questions or want help implementing this? Feel free to reach out or drop your thoughts in the comments. Let's build secure, user-friendly software together.

Ready To Unleash The Power of ERPNext?

We might just be the right partner you need.


No comments yet.

Add a comment
Ctrl+Enter to add comment