Antivirus Scanning (ClamAV)

Honse Farm supports optional server-side antivirus scanning of all uploaded files using ClamAV. When enabled, every file uploaded by a client is decompressed and streamed to a local ClamAV daemon for inspection before it is persisted to disk. Infected files are rejected, the uploading user is flagged for admin review, and the file hash is permanently banned from future uploads across the federation.

How It Works

The scanning pipeline is transparent to server owners once enabled. The following describes what happens on a server level when a client uploads a file:

  1. Decompression — The uploaded file is LZ4-decompressed in memory (this data already exists for hash verification, so no additional memory is allocated for scanning).
  2. Hash Pre-Check — Before calling ClamAV, the server checks its ForbiddenUploadEntries table. If the file hash was already flagged by a previous scan, the upload is immediately rejected without touching ClamAV.
  3. Deduplication — If the exact file (same hash and size) was already scanned and recorded as clean, ClamAV is not called again.
  4. ClamAV Scan — The decompressed file data is streamed over TCP to the ClamAV daemon. ClamAV performs signature-based and heuristic analysis.
  5. Infected File Handling — If ClamAV detects a threat:
    • The file is rejected and not written to disk.
    • The file hash is added to the ForbiddenUploadEntries table, preventing any future upload of the same file by any user on any federated server.
    • A UserReview entry is created (or appended to) for the uploading user, flagging them for admin investigation.
    • The client receives a notification identifying the blocked mod by name.
  6. Clean File Handling — If ClamAV reports the file as clean, the scan result is persisted so the same file is never scanned twice.
  7. Graceful Degradation — If ClamAV is unreachable or returns an error, the upload is allowed through. The server logs a warning but does not block the upload. This prevents ClamAV downtime from breaking your server's upload functionality entirely.

All three upload paths are covered: regular uploads, munged (XOR-obfuscated) uploads, and chunked uploads.

Requirements

ClamAV runs as a sidecar Docker container alongside your fileserver(s). Be aware of the following resource requirements:

Memory Requirements

ClamAV requires 2 – 2.5 GB of RAM to load its virus signature database into memory. This is a fixed cost per ClamAV instance regardless of how many files are scanned. Ensure your server has sufficient memory available before enabling this feature.

  • Docker image: clamav/clamav:stable
  • Default port: 3310 (TCP, internal only — not exposed to the internet)
  • Persistent storage: A named Docker volume (clamav_data) is used to persist the virus signature database at /var/lib/clamav. This prevents ClamAV from re-downloading the full signature database on every container restart.
  • Automatic updates: The ClamAV stable image includes a built-in freshclam process that automatically updates virus definitions in the background. No separate sidecar is required.

Configuration

Antivirus scanning is controlled by two settings in your fileserver's appsettings.Production.json:

{
  "ClamAntivirusEnabled": true,
  "ClamAntivirusUri": "tcp://clamav:3310"
}
SettingTypeDefaultDescription
ClamAntivirusEnabledboolfalseEnables or disables ClamAV scanning for this fileserver. When false, no files are scanned and the ClamAV container is not required.
ClamAntivirusUristringThe TCP URI of the ClamAV daemon. Format: tcp://<hostname>:<port>. When using the default Docker Compose setup, this is tcp://clamav:3310.

Per-Fileserver Setting

Each fileserver has its own configuration. If you run multiple fileservers, you must enable and configure ClamAV for each one individually. All fileservers can point to the same ClamAV container.

Docker Compose Setup

If you are using the installer, the ClamAV container and volume are configured automatically when you enable antivirus during setup.

For manual deployments, add the following to your docker-compose.yml:

services:
  clamav:
    image: clamav/clamav:stable
    restart: always
    ports:
      - "3310:3310"
    volumes:
      - clamav_data:/var/lib/clamav

volumes:
  clamav_data:

Then ensure your fileserver service(s) include a depends_on entry for clamav and have the configuration values set in their respective appsettings files.

Enabling via the Installer

The Honse Farm installer includes an Antivirus configuration screen. When enabled:

  • The installer adds the ClamAV container to your generated docker-compose.yml
  • The clamav_data volume is created for signature persistence
  • Each fileserver's appsettings is configured with ClamAntivirusEnabled: true and the correct ClamAntivirusUri
  • Fileserver containers are set to depend on the ClamAV container

What Happens to the User

When a client uploads a file that ClamAV detects as malicious:

  • The upload is rejected immediately.
  • The client receives a notification: "The mod you have just tried to sync contains malicious payloads and has been blocked for distribution. Additionally, your account has been flagged for review. Remove the mod in question and please try again." — including the name of the Penumbra mod containing the flagged file.
  • The user is flagged for admin review in the user_admin_review table. Subsequent violations append to the same review entry.
  • The file hash is permanently banned. Even if the user removes the flag, the same file cannot be uploaded again by any user.

Admin Review

Flagged users can be reviewed through the admin panel. Each UserReview entry created by ClamAV includes:

  • The hash of the infected file
  • The threat name reported by ClamAV
  • A timestamp of when the flag was created

Multiple violations by the same user are appended as additional remarks to their existing review entry.

Limitations

  • Signature-based detection only — ClamAV detects known malware signatures. It is not a sandbox or behavioral analysis engine. Novel or highly obfuscated threats may not be detected.
  • Memory cost is fixed — The 2–2.5 GB memory footprint exists regardless of scan volume. There is no way to reduce this.
  • Graceful degradation means no blocking on failure — If ClamAV goes down, uploads are allowed through. Monitor your ClamAV container health if you rely on scanning as a security measure.