Block malware in uploads
Your service accepts files — attachments, avatars, documents, imports. Anything a user uploads is content you did not write, arriving inside a request your application is about to trust.
Scan the upload path, and only the upload path
Content scanning hands the request body to ClamAV before it is forwarded upstream. A signature hit refuses the request with 403, so infected content never reaches your storage, your queue or a downstream worker.
It is proxy-mode only, for the obvious reason: something has to have the decrypted body.
The scanner is armed in configuration and aimed by a rule. Enabling it on its own scans nothing:
proxy:
content_scanning:
enabled: true
clamav_server: "localhost:3310"
max_file_size: 10485760
unscannable: block
Then write a WAF rule with the content_scanning action to select the
traffic:
starts_with(http.request.path, "/upload")
Everything outside that path is untouched and costs nothing — which is the whole point. Scanning every request body would put a ClamAV round trip in front of every API write.
enabled: true with no content_scanning rule inspects nothing, and the agent says so on
every load: content scanning is enabled but no WAF rule uses the content_scanning action.
Decide what happens to what you cannot scan
An upload can be selected by your rule and still be uninspectable — over max_file_size, or
chunked past it. unscannable is that decision, and it defaults to refusing:
block (default) | Refuse with 413. The rule asked for a guarantee that could not be provided. |
pass | Forward unscanned, logged. Oversized uploads keep working; they reach the backend uninspected. |
Choosing pass is legitimate — just make it deliberately, because it is the setting that
quietly turns a scanned endpoint into a partially scanned one.
Where this stops working
The playground has a Malware Upload scenario that walks the file through content scanning and shows the refusal, with no ClamAV to stand up.
- ClamAV is signature-based. It catches known malware. It does not catch a targeted payload written for you.
- The scanner fails open. If ClamAV is unreachable the request proceeds and the failure is logged. Alert on scan failures; a quietly dead scanner looks identical to a clean one.
- Only what your rule selects is scanned. That is the design, but it means a second upload endpoint added later is unprotected until the rule covers it.
- Latency scales with body size, plus a round trip, on the selected traffic.
- You need a ClamAV you run and keep updated. A stale signature database is a quiet failure.
- Requires Synapse 0.8.3 or newer. Older builds have no working way to select traffic.
See also
- Content Scanning — the full behaviour, memory budget and verdict cache
- WAF — the rule engine and the
content_scanningaction - Security Event Export — records of what was refused