| name | file-upload-virus-scanning |
| description | Use when designing malware and content scanning for files uploaded to Salesforce (Files, Attachments, ContentVersion) — external scanning service callouts, quarantine patterns, and user-facing messaging. Triggers: 'virus scan salesforce upload', 'malware scan content version', 'quarantine uploaded file', 'clamav salesforce', 'file upload security'. NOT for field-level data validation. |
| category | security |
| salesforce-version | Spring '25+ |
| well-architected-pillars | ["Security","Reliability","User Experience"] |
| triggers | ["scan uploaded files for malware","how to integrate clamav with salesforce files","quarantine infected contentversion","virus scan experience cloud uploads","customer-facing portal file scan"] |
| tags | ["security","files","malware-scanning","quarantine","content-version"] |
| inputs | ["upload surfaces (LWC, Experience Cloud, Email-to-Case, API)","scanning service (ClamAV, Cloudmersive, third-party)","quarantine policy and user-facing behavior"] |
| outputs | ["scan integration design","quarantine state machine","user-facing messaging for infected/pending states"] |
| dependencies | [] |
| version | 1.0.0 |
| author | Pranav Nagrecha |
| updated | 2026-04-23T00:00:00.000Z |
File Upload Virus Scanning
Salesforce does not scan files. Any file uploaded into ContentVersion, Attachment, or a Document object is trusted bytes until you prove otherwise. For internal-only orgs the risk is moderate; for Experience Cloud portals, Email-to-Case, partner portals, and any surface that accepts uploads from unauthenticated or lightly authenticated users, the risk is substantial. Ransomware, credential stealers, and polyglot files routinely ride in on expected-looking PDFs and spreadsheets.
The architecture is the same across scanning providers: intercept uploads, send the byte stream (or hash) to a scanning service, route based on the verdict, and expose state to consumers. The design choices are where to intercept, how to handle large files, what "pending" looks like to the user, and how to quarantine without deleting audit trail.
Before Starting
- List every upload surface: LWC components, standard pages, Email-to-Case, Web-to-Case, API integrations, Experience Cloud, mobile app.
- Identify the file types and size ranges in scope.
- Choose scanning service (hosted ClamAV, Cloudmersive Virus Scan, MetaDefender, etc.) — confirm SLA and throughput.
- Define quarantine policy: block, allow-with-warning, or allow-after-review.
Core Concepts
Interception Points
- Pre-save trigger on ContentVersion — inspects inserts before the file is indexed/shared.
- Post-save async on ContentVersion — scans via a Queueable after commit; toggles a
ScanStatus__c field.
- Flow on Attachment — legacy object; same pattern.
- Middleware interception — scan happens in MuleSoft / Apigee before Salesforce sees the bytes.
Pre-save interception is cleanest but blocks the user on scan latency. Post-save async avoids the block at the cost of a scan-pending window.
State Machine
A scanned file should live in one of:
Scan_Pending — uploaded, not yet scanned.
Scan_Clean — passed; fully available.
Scan_Infected — failed; quarantined.
Scan_Error — scanner unreachable; policy decides (block or allow-with-warning).
Sharing, preview, and download must honor the state. Scan_Pending files should typically not be previewable or shareable externally.
Quarantine Without Deletion
Deleting infected files destroys audit trail. Preferred: retain the ContentVersion record with restricted sharing, strip the preview, redact the blob (or move to a dedicated quarantine library), and mark the state.