From 3e147554ebd4fc49d1dcd9766452e0ae8bc69ceb Mon Sep 17 00:00:00 2001 From: Thore Cimbal Date: Wed, 29 Jul 2026 18:40:35 +0200 Subject: [PATCH] docs: document client-side scan patches and Electron/desktop caveat (Issue #19) --- .../06-moderation-content-scanning.md | 67 +++++++++++++++++-- 1 file changed, 63 insertions(+), 4 deletions(-) diff --git a/docs/deployment-guides/06-moderation-content-scanning.md b/docs/deployment-guides/06-moderation-content-scanning.md index 975f852..6f628c4 100644 --- a/docs/deployment-guides/06-moderation-content-scanning.md +++ b/docs/deployment-guides/06-moderation-content-scanning.md @@ -126,7 +126,66 @@ schließt genau diesen Callback explizit aus), daher selbst geschrieben. Grenze: Synapse hat bei E2EE nie den Entschlüsselungsschlüssel, sieht nur Ciphertext. Nur ein kooperierender Client könnte das lösen (siehe oben, existiert nicht offen verfügbar). -**Bekannte Deckungslücke**: schützt nur unverschlüsselte Räume/DMs (viele öffentliche/ -föderierte Räume) - keine Warnung/Kennzeichnung für Nutzer in verschlüsselten Räumen, dass -dort kein Scanning stattfindet. Folgeidee (Issue #43, LOW): Grafana-Dashboard über die -bestehenden Loki-Logs, um Erkennungen/Scanner-Ausfälle sichtbar zu machen. +**Bekannte Deckungslücke (Stand vor der Client-Erweiterung unten)**: schützt nur +unverschlüsselte Räume/DMs - keine Warnung/Kennzeichnung für Nutzer in verschlüsselten +Räumen, dass dort kein Scanning stattfindet. Folgeidee (Issue #43, LOW): Grafana-Dashboard +über die bestehenden Loki-Logs, um Erkennungen/Scanner-Ausfälle sichtbar zu machen. + +## 3. Client-seitiges Scanning für verschlüsselte Räume (Issue #19-Erweiterung, 2026-07-29) + +Da Synapse bei E2EE-Räumen strukturell nie den Schlüssel hat, kann nur der **Client** +Klartext scannen - einmal beim Senden (vor der Verschlüsselung), einmal beim Empfangen +(nach der Entschlüsselung). Umgesetzt in `ThreadNet-Web` (Fork von Element Web). + +### Architektur + +Ein neuer, eigener HTTP-Dienst (`apps/production/clamav-http-scanner.py`, eigenes Image via +`clamav-http-scanner-Dockerfile`) macht denselben ClamAV-Pod für Browser-JS erreichbar +(clamd spricht nur rohes TCP, das kann ein Browser nicht). Erreichbar unter +`https://axion1337.chat/_scan`. Auth über Synapses eigenen +`/_matrix/client/v3/account/whoami`-Endpunkt (kein eigenes Auth-System nötig) - verhindert, +dass der Dienst zu einem offenen "teste dein Malware gegen unseren Virenscanner"-Orakel für +das ganze Internet wird. Fail-open bei Scanner-Fehlern, wie beim Synapse-Modul. + +**Zwei Patch-Stellen im `ThreadNet-Web`-Fork** (im Repo +`rohana.axion1337.de/sorb/ThreadNet-Web.git`, nicht in diesem gitops-Repo): + +- **Empfang**: `apps/web/src/utils/DecryptFile.ts`, Funktion `decryptFile()` - der einzige + Punkt im ganzen Client, an dem entschlüsselte Klartext-Bytes für *jeden* Anhangstyp + entstehen (Bild/Audio/Video/Datei laufen alle über `MediaEventHelper` hier durch). Scan + direkt nach dem Entschlüsseln, vor der Rückgabe als `Blob`. +- **Versand**: `apps/web/src/ContentMessages.ts`, Funktion `uploadFile()` - die eine + gemeinsame Funktion für alle Anhangs-Uploads (Hauptdatei, generierte Thumbnails, + Sprachnachrichten), unabhängig davon ob der Zielraum verschlüsselt ist. Scan direkt nach + dem Einlesen der Datei, vor Verschlüsselung/Upload. +- Gemeinsame Hilfsdatei: `apps/web/src/utils/ContentScanner.ts` (neue `scanContent()`- + Funktion + `ContentScanRejectedError`), von beiden Stellen genutzt. Fehlertexte über die + bereits bestehenden Error-Rendering-Pfade in `MImageBody.tsx`/`MAudioBody.tsx`/ + `VideoBodyViewModel.ts`/`FileBodyViewModel.ts` (gleiches Muster wie die schon vorhandenen + `DecryptError`/`DownloadError`). + +**Live getestet** (2026-07-29): EICAR in verschlüsseltem Gruppenraum ("testgruppe") und in +1:1-DMs zwischen zwei echten Accounts - in beiden Fällen zuverlässig **vor dem Upload** +blockiert. Vorher (nur Synapse-Modul) lief das durch. + +### ⚠️ Wichtig für zukünftige Desktop-/Electron-Forks + +**Dieser Fix gilt nur für den Web-Client (Browser), nicht automatisch für Element Desktop.** + +Element Desktop (`apps/desktop` im selben Monorepo) ist ein Electron-Wrapper, der die +Web-App nicht selbst baut, sondern per `scripts/fetch-package.ts` ein fertiges, +**offiziell von `element-hq/element-web` signiertes Release-Tarball** herunterlädt und in +ein `webapp.asar` packt (`pnpm run fetch` → `pnpm run asar-webapp`). Ohne weitere Änderung +würde ein Desktop-Build also die **unveränderte Upstream-Version** bündeln - unsere Patches +wären nicht drin, obwohl sie im selben Monorepo liegen. + +**Für einen zukünftigen Desktop-Fork mit dieser Funktion**: `fetch-package.ts` akzeptiert +bereits eine beliebige URL statt einer Versionsnummer als Override +(`targetVersion.includes("://")`-Zweig, keine Code-Änderung nötig) - man müsste nur unseren +eigenen `apps/web`-Build als `.tar.gz` irgendwo selbst hosten (z.B. als Gitea-Release-Asset) +und `pnpm run fetch https://.../unser-build.tar.gz` statt der Standard-Versionsnummer +aufrufen. + +**Element X (Mobile, iOS/Android)** ist davon komplett unberührt - eigene Codebasis auf +Basis von `matrix-rust-sdk`, kein gemeinsamer Code mit `ThreadNet-Web`. Ein Schutz dort +wäre ein separates, eigenständiges Projekt.