Skip to main content

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.

If nothing is being scanned, look for the rule

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.
passForward 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

See it happen first

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