Malware Scanning
PentestPad can scan every uploaded file for malware before it is stored or served — project attachments, finding and editor images, report template and PDF replacements, and whitelabel logos. Scanning is handled by a ClamAV clamd sidecar container that the application streams uploads to.
On PentestPad Cloud this is always on. On self-hosted instances it is opt-in: you add the ClamAV container and set a single environment variable.
1. Add the ClamAV container
Section titled “1. Add the ClamAV container”Add the clamav service to your docker-compose.yml, alongside the existing PentestPad services:
services: # ... existing app, postgres, redis services ...
clamav: image: clamav/clamav:1.4-debian container_name: clamav restart: unless-stopped volumes: # Persist downloaded signatures so the slow first pull only happens once. - clamav_db:/var/lib/clamav - ./clamd.conf:/etc/clamav/clamd.conf:ro healthcheck: # Image-provided helper: PINGs clamd, exits non-zero until ready. test: ["CMD", "clamdcheck.sh"] interval: 30s timeout: 10s retries: 5 start_period: 120s networks: - app_network
volumes: clamav_db:Then declare the dependency on the app service so it starts after ClamAV, and point it at the sidecar:
services: app: depends_on: clamav: condition: service_started environment: CLAMAV_HOST: clamavclamd listens on TCP port 3310 and is reached only over the internal app_network — there is no need to publish a host port.
2. Provide clamd.conf
Section titled “2. Provide clamd.conf”The mounted clamd.conf raises clamd’s size limits so large attachments (up to ~700 MB) can be scanned. The stock image defaults to only 25 MB per stream and 400 MB per file, which would silently leave large uploads unscanned — so this file is required.
Create clamd.conf next to your docker-compose.yml:
LogFile /var/log/clamav/clamd.logLogTime yes
# Bind all interfaces (dual-stack) so the image's clamdcheck.sh healthcheck,# which PINGs IPv6 localhost, keeps working. Do not pin TCPAddr.LocalSocket /tmp/clamd.sockTCPSocket 3310User clamav
# Raise the limits well above the ~700 MB attachment cap. The application# enforces a matching ceiling via CLAMAV_MAX_STREAM_BYTES.StreamMaxLength 768MMaxScanSize 768MMaxFileSize 768M3. Enable scanning
Section titled “3. Enable scanning”Set the master switch in your .env and restart the app:
SCANNING_ENABLED=trueWhen scanning is disabled (the self-hosted default), the application behaves exactly as before — no scan records are created and no jobs are queued.
The remaining variables have sensible defaults that match the container above; override them only for a non-standard setup (for example an external clamd):
| Environment variable | Default | Purpose |
|---|---|---|
SCANNING_ENABLED | false (self-hosted) | Master on/off switch. |
CLAMAV_HOST | clamav | Hostname of the clamd sidecar. |
CLAMAV_PORT | 3310 | clamd TCP port. |
CLAMAV_TIMEOUT | 120 | Socket timeout, in seconds, for a single scan. |
CLAMAV_MAX_STREAM_BYTES | 805306368 (768 MB) | Largest file streamed to clamd; bigger files are recorded as unscannable. Must stay ≤ clamd’s StreamMaxLength. |
CLAMAV_SYNC_MAX_BYTES | 134217728 (128 MB) | Largest file scanned in-request at upload time. Bigger files are accepted and scanned in the background. |
CLAMAV_STALE_AFTER_MINUTES | 60 | How long a scan may sit pending before the recovery sweep re-runs or escalates it. |
4. Make sure the queue worker is running
Section titled “4. Make sure the queue worker is running”Files larger than CLAMAV_SYNC_MAX_BYTES (128 MB by default), plus any uploads accepted while the scanner was briefly unreachable, are scanned in the background on a dedicated scans queue. The standard PentestPad image runs Laravel Horizon, which already drains this queue — just make sure Horizon is running.
5. Verify
Section titled “5. Verify”- Start the stack:
docker compose up. - Confirm the sidecar is healthy:
docker compose psshould showclamavashealthy(allow ~2 minutes on first boot). - Upload a normal file in a project — it should attach without any warning badge.
- To safely confirm detection works, upload an EICAR test file — a harmless standard antivirus test string. The upload should be blocked by malware scanning.
Once verified, see Attachment Scanning for what your team sees day to day — the scan badges, the blocked-upload flow, and downloading flagged files safely.