3D-Illustration eines digitalen Tresors mit einem leuchtenden Sicherheitsschloss, das einen Entschlüsselungsfehler anzeigt, umgeben von Docker-Containern und Code-Zeilen.

Wenn Bitwarden plötzlich schweigt: WebAssembly, Vaultwarden 1.37.0 und die Nginx-CSP-Falle

Self-Hosting macht Spaß – bis der Passwort-Manager plötzlich den Dienst verweigert. Bei mir blieb die Bitwarden Browser-Extension kürzlich in einer endlosen Ladeschleife hängen, und im Web-Vault begrüßten mich einzelne Einträge mit der ungemütlichen Meldung [error: cannot decrypt].

Kein Panikmoment, sondern ein perfektes Lehrbeispiel dafür, wie verschachtelt moderne Web-Anwendungen, Docker-Container und Sicherheits-Header miteinander interagieren.

Hier ist die Geschichte der Fehlersuche und wie sich das Problem lückenlos lösen ließ.

Das Fehlerbild: Wenn die Entschlüsselung hakt

Das Symptom war tückisch:

  • Der Login am Web-Vault funktionierte problemlos.
  • Einzelne Einträge ließen sich öffnen, andere zeigten beim Anklicken nur [error: cannot decrypt].
  • Die Browser-Extension blieb beim Synchronisieren komplett stecken.

Der erste Impuls bei Datenbank-basierten Containern: Ist die SQLite-Datei korrupt? Ein kurzer Check via PRAGMA integrity_check lieferte jedoch ein beruhigendes ok. Auch die Datenstrukturen in der ciphers-Tabelle waren vollkommen intakt.

Die Ursache lag nicht in zerstörten Daten, sondern in zwei aufeinanderfolgenden Versions- und Sicherheits-Barrieren.

Die Ursachenkette: Versionen & WebAssembly

1. Der Client-Server-Mismatch (Vaultwarden 1.36.0 vs. Client 2026+)

Bitwarden hat das Sicherheitskonzept für Tresor-Einträge erweitert (Per-Item Encryption Keys). Neue Client-Apps und Browser-Extensions verschlüsseln Einträge nun mit individuellen Schlüsseln.

Wird der Vaultwarden-Server nicht parallel aktualisiert, versteht der alte Server (v1.36.0) die vom neuen Client geschriebenen Datensätze nicht mehr sauber. Die Folge: Die Extension versucht vergebens, den Eintrag mit veralteten Protokollen zu entschlüsseln, und bricht den Sync-Prozess ab.

Erste Erkenntnis: Der Server musste auf Vaultwarden 1.37.0+ gehoben werden, um die neuen Krypto-Handshakes der Clients zu unterstützen.

2. Der eigentliche Showstopper: Content Security Policy (CSP)

Nach dem Update von Vaultwarden folgte der nächste Überraschungsmoment: Der Web-Vault verharrte in einem dauerhaften Lade-Spinner.

Ein Blick in die Browser-Entwicklerwerkzeuge (F12 → Konsole) förderte den wahren Täter zutage:

Content-Security-Policy: Die Einstellungen der Seite haben die Ausführung eines
WebAssembly (script-src) blockiert, da es gegen folgende Direktive verstößt:
"script-src 'self'"

Was war passiert?

Der neue Web-Vault von Bitwarden nutzt für die clientseitige Entschlüsselung ein performantes WebAssembly (WASM)-Modul (bitwarden_wasm_internal_bg.wasm).

Mein Nginx Proxy Manager lieferte jedoch einen sehr strengen Sicherheits-Header aus: script-src 'self'. Modernes WebAssembly wird von Browsern aus Sicherheitsgründen aber strikt blockiert, wenn die CSP nicht explizit grünes Licht dafür gibt. Das Krypto-Modul konnte nicht geladen werden, die Entschlüsselung schlug fehl.

Die Lösung: Container-Update & CSP-Anpassung

Die Behebung erforderte zwei gezielte Schritte:

Schritt 1: Vaultwarden auf Version 1.37.0+ bringen

Über Portainer bzw. Docker Compose wurde das aktuelle Image gezogen und der Container neu bereitgestellt:

docker compose pull && docker compose up -d

Schritt 2: Reverse Proxy Header anpassen

Im Nginx Proxy Manager musste die Content Security Policy unter den erweiterten Nginx-Einstellungen (Advanced Tab) um die Direktive 'wasm-unsafe-eval' erweitert werden:

add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' wss: https:;" always;

💡 Sicherheitshinweis: 'wasm-unsafe-eval' erlaubt zielgerichtet ausschließlich das Ausführen von kompiliertem WebAssembly. Es öffnet nicht die klassische, gefährliche 'unsafe-eval'-Lücke für beliebiges JavaScript!

Fazit & Takeaway

Nach dem Leeren des Browser-Caches lief der Tresor sofort wieder blitzschnell.

Was lernen wir daraus für das eigene Homelab?

  1. Security-Header müssen mitwachsen: Wenn Web-Anwendungen auf neuere Web-Standards wie WASM umstellen, müssen vorgeschaltete Reverse Proxies (Nginx, Traefik, Caddy) angepasst werden.
  2. Keine voreiligen Datenbank-Eingriffe: Ein [error: cannot decrypt] bedeutet nicht automatisch, dass Datensätze gelöscht werden müssen. Oft stimmen lediglich die Schlüsselverhandlung oder die Ausführungsrechte im Browser nicht.

🔗 Weiterführende & Nützliche Links

Ähnliche Beiträge

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert