Bulwark Webmail: Plugin-Sandbox nimmt Code von jeder fremden Seite an

Die Sandbox-Routen sind unangemeldet erreichbar, tragen unsafe-eval und binden sich an das erste Fenster, das ihnen schreibt, ohne dessen Herkunft zu pruefen

Advisory-ID: TP-2026-103
Produkt: Bulwark Webmail (Weboberflaeche fuer den Mailserver Stalwart, Next.js)
Schwachstellentyp: Fehlende Herkunftspruefung (CWE-346)
CVE: beantragt am 19. September 2026 (GitHub CNA), Vergabe ausstehend
CVSS 3.1: 8.8 (Hoch) · CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Betroffene Versionen: >= 1.7.0, <= 1.9.2
Hersteller-Advisory: GHSA-96cx-gx36-3g79
Behoben in: 1.10.0
Gemeldet: 16. September 2026

Zusammenfassung

Bulwark fuehrt Erweiterungen in zwei eigenen Dokumenten aus, die als oberste Seiten erreichbar sind und unsafe-eval tragen. Ihr Nachrichten-Handler merkt sich das erste Fenster, das ihm eine Nachricht schickt, und vergleicht dessen Herkunft nie mit der eigenen. Eine beliebige fremde Seite oeffnet also eine dieser Routen, schickt ihre Einrichtungsnachricht vor dem echten Wirtsfenster, und die darin enthaltene Zeichenkette erreicht new Function innerhalb der Herkunft der Webmail. Die Vertrauenskette der Erweiterungen wird dabei nie befragt, denn die Pruefung der Signatur und des Pruefwerts liegt in Modulen, die die Laufzeitumgebung der Sandbox gar nicht einbindet. Ein Abschalten der Erweiterungen hilft nicht, da die Routen auch dann mit Erfolg antworten.

Ursache

Die Laufzeitumgebung der Sandbox nimmt die erste eingehende Nachricht von einem beliebigen Fenster an und merkt sich dessen Referenz als Wirt, ohne die Herkunft zu pruefen (lib/plugin-sandbox/runtime.tsx:628-636). Die Routen /plugin-sandbox und /plugin-sandbox-privileged sind oberste Dokumente ohne Anmeldung und tragen unsafe-eval, weshalb die uebergebene Zeichenkette ueber new Function ausgefuehrt wird. Die Vertrauenskette der Erweiterungen bleibt unberuehrt: die Ed25519-Signatur wird dort geprueft, wo der Katalog ein Paket herunterlaedt, und Pruefwert sowie Stufe prueft der Lader, waehrend die Laufzeitumgebung keines dieser Module einbindet. Die Einstellung fuer Erweiterungen steht ab Werk auf aus und schuetzt nicht, da die Routen auch dann mit Erfolg und ohne Cookie antworten. Der Handler ist in allen vierzehn Ausgaben von 1.7.0 bis 1.9.2 byteweise identisch; Fassungen bis 1.6.7 bringen gar keine Sandbox mit.

Proof of Concept

# Beliebige fremde Seite, die das angemeldete Opfer besucht:
const w = window.open('https://webmail.example/plugin-sandbox');
// Vor dem echten Wirtsfenster die Einrichtungsnachricht schicken:
w.postMessage({type: 'init', code: '<javascript des angreifers>'}, '*');

// Der Handler merkt sich das erste Fenster als Wirt, prueft dessen
// Herkunft nicht, und new Function fuehrt den Code in der Herkunft
// der Webmail aus.

Ein Klick des angemeldeten Opfers auf der fremden Seite genuegt. Die Route /plugin-sandbox allein reicht aus; die privilegierte Variante gibt es seit 1.7.6 und verhaelt sich gleich. Der Code laeuft auch ohne Anmeldung, nur die Wirkung setzt eine angemeldete Sitzung voraus.

Auswirkung

  • Ausfuehrung beliebigen JavaScripts in der Herkunft der Webmail durch eine fremde Seite nach einem Klick des Opfers.
  • Auslesen der Sitzung und Steuerung des JMAP-Durchgriffs im Namen des Opfers.
  • Kein Konto auf der Instanz noetig, der Angriff beginnt auf einer beliebigen fremden Seite.
  • Kein Schutz durch das Abschalten der Erweiterungen, da die Routen unabhaengig davon antworten.

Referenzen

Steckt so etwas in Ihrer Software?

Diese Schwachstelle hat unser Team im Rahmen seiner Arbeit gefunden. Lassen Sie Ihre Anwendungen von denselben Spezialisten prüfen, mit einem Penetrationstest von turingpoint.