feat: client-side ClamAV scanning for encrypted rooms (Issue #19)
Synapse's own check_media_file_for_spam module can never see E2EE attachment content - only the client ever holds the decryption key. Adds two hooks that call a self-hosted scan service (https://axion1337.chat/_scan, deployed separately in the gitops repo): - DecryptFile.ts: scans every decrypted attachment (image/audio/video/ file all funnel through this one function via MediaEventHelper) before returning it as a Blob. - ContentMessages.ts: scans plaintext before encryption/upload in uploadFile(), the shared function behind all attachment uploads (main file, thumbnails, voice messages), regardless of room encryption state. New ContentScanRejectedError surfaces through the existing error- rendering paths (MediaProcessingError, upload failure dialog) using the same pattern as DecryptError/DownloadError/UploadFailedError. Live-tested: EICAR blocked pre-upload in encrypted rooms and DMs; receive-side hook also blocks EICAR sent by an unpatched client (app.element.io), confirming it isn't just self-protection for our own uploads. Fails open on scanner errors so an outage can't block all uploads/downloads.
This commit is contained in:
@@ -3400,7 +3400,8 @@
|
||||
"m.audio": {
|
||||
"error_downloading_audio": "Error downloading audio",
|
||||
"error_processing_audio": "Error processing audio message",
|
||||
"error_processing_voice_message": "Error processing voice message"
|
||||
"error_processing_voice_message": "Error processing voice message",
|
||||
"error_scan_rejected": "This audio was blocked by the content scanner"
|
||||
},
|
||||
"m.beacon_info": {
|
||||
"view_live_location": "View live location"
|
||||
@@ -3432,12 +3433,14 @@
|
||||
"voice_call_unsupported": "%(senderName)s placed a voice call. (not supported by this browser)"
|
||||
},
|
||||
"m.file": {
|
||||
"error_decrypting": "Error decrypting attachment"
|
||||
"error_decrypting": "Error decrypting attachment",
|
||||
"error_scan_rejected": "This file was blocked by the content scanner"
|
||||
},
|
||||
"m.image": {
|
||||
"error": "Unable to show image due to error",
|
||||
"error_decrypting": "Error decrypting image",
|
||||
"error_downloading": "Error downloading image",
|
||||
"error_scan_rejected": "This image was blocked by the content scanner",
|
||||
"sent": "%(senderDisplayName)s sent an image.",
|
||||
"show_image": "Show image"
|
||||
},
|
||||
@@ -3563,6 +3566,7 @@
|
||||
"m.sticker": "%(senderDisplayName)s sent a sticker.",
|
||||
"m.video": {
|
||||
"error_decrypting": "Error decrypting video",
|
||||
"error_scan_rejected": "This video was blocked by the content scanner",
|
||||
"show_video": "Show video"
|
||||
},
|
||||
"m.widget": {
|
||||
@@ -3805,6 +3809,7 @@
|
||||
"title": "Allow guest users to join this room"
|
||||
},
|
||||
"upload_failed_generic": "The file '%(fileName)s' failed to upload.",
|
||||
"upload_failed_scan_rejected": "The file '%(fileName)s' was blocked by the content scanner.",
|
||||
"upload_failed_size": "The file '%(fileName)s' exceeds this homeserver's size limit for uploads",
|
||||
"upload_failed_title": "Upload Failed",
|
||||
"upload_file": {
|
||||
|
||||
Reference in New Issue
Block a user