Element Web
Ungefilterte HTML-Injection über die homeserver-kontrollierte Startseiten-URL
Die Komponente EmbeddedPage lädt die Startseite von einer konfigurierbaren URL und rendert die Antwort ohne Bereinigung über dangerouslySetInnerHTML. Setzt ein Deployment embedded_pages.home_url nicht in der eigenen Konfiguration, wird diese URL aus dem .well-known/matrix/client-Dokument des Homeservers gelesen. Ein bösartiger Homeserver-Betreiber kann damit beliebiges Markup in den Client jeder Person einschleusen, die sich gegen diesen Server anmeldet. Die Content Security Policy verhindert die Ausführung von JavaScript, frame-src * lässt aber Credential-Phishing über ein eingeschleustes Iframe zu.
Beschreibung
EmbeddedPage lädt die konfigurierte Startseite per HTTP und legt den Antwort-Body im Component-State ab. Die Bibliothek sanitize-html wird in derselben Datei importiert, aber nur für die Ersetzung der Übersetzungs-Strings auf dem Weg hinein. Der Body selbst durchläuft sie nie.
EmbeddedPage.tsx:76-88 (v1.12.21)
// Replace '," and HTML encoded variantslet body = (await res.text()).replace( /_t\((?:['"]|(?:&#(?:34|27);))([\s\S]*?)(?:['"]|(?:&#(?:34|27);))\)/gm, (match, g1) => this.translate(g1),);
if (this.props.replaceMap) { Object.keys(this.props.replaceMap).forEach((key) => { body = body.split(key).join(this.props.replaceMap![key]); });}
this.setState({ page: body });Der abgelegte Body wird anschließend direkt in den Component-Tree gerendert:
EmbeddedPage.tsx:128 (v1.12.21)
const content = <div className={`${className}_body`} dangerouslySetInnerHTML={{ __html: this.state.page }} />;Die URL stammt aus getHomePageUrl(). Die Funktion bevorzugt die config.json des Deployments und fällt auf den Homeserver zurück, wenn dieser Schlüssel fehlt:
pages.ts:15-26 (v1.12.21)
export function getHomePageUrl(appConfig: IConfigOptions, matrixClient: MatrixClient): string | undefined { const config = new SnakedObject(appConfig);
const pagesConfig = config.get("embedded_pages"); let pageUrl = pagesConfig ? new SnakedObject(pagesConfig).get("home_url") : null;
if (!pageUrl) { pageUrl = getEmbeddedPagesWellKnown(matrixClient)?.home_url; }
return pageUrl;}WellKnownUtils.ts:16, 68-74 (v1.12.21)
const EMBEDDED_PAGES_WK_PROPERTY = "io.element.embedded_pages";
export function getEmbeddedPagesWellKnown(matrixClient: MatrixClient | undefined): IEmbeddedPagesWellKnown | undefined { return embeddedPagesFromWellKnown(matrixClient?.getClientWellKnown());}
export function embeddedPagesFromWellKnown(clientWellKnown?: IClientWellKnown): IEmbeddedPagesWellKnown { return clientWellKnown?.[EMBEDDED_PAGES_WK_PROPERTY];}Der Lesevorgang ist ein reiner Property-Zugriff: keine Prüfung, keine Einschränkung der Herkunft über den eigenen Homeserver hinaus. getEmbeddedPagesWellKnown() liefert io.element.embedded_pages.home_url aus dem .well-known/matrix/client-Dokument dieses Homeservers. Dieser Fallback kam mit Pull Request #7790 ins matrix-react-sdk; das ungefilterte Rendern ist älter. Ein Deployment, das embedded_pages.home_url in der eigenen config.json setzt, erreicht den Fallback nie. Die Angreifbarkeit hängt also ebenso an der Deployment-Konfiguration wie an der Client-Version.
Aus der Injection wird keine Ausführung von JavaScript. Grund dafür ist die ausgelieferte Content Security Policy, die zugleich bestimmt, was übrig bleibt:
| Direktive | Wert | Konsequenz |
|---|---|---|
script-src | 'self' 'wasm-unsafe-eval' (plus reCAPTCHA) | Inline-Scripts blockiert. Kein XSS. |
frame-src | * blob: data: | Ein Angreifer-Iframe innerhalb der vertrauten Oberfläche. Das ist das Phishing-Primitive. |
form-action | 'self' | Blockiert einen direkten POST aus dem eingeschleusten Markup, nicht aber einen aus dem Iframe heraus. |
style-src | 'self' 'unsafe-inline' | Eingeschleuste style-Blöcke gestalten die umgebende Oberfläche um. |
img-src | * blob: data: | Tracking-Pixel und CSS-basierte Beacons. |
connect-src | * blob: | Der Body der Startseite darf von jeder Origin geladen werden. |
base-uri | nicht gesetzt | Keine Einschränkung für ein eingeschleustes base-Tag. Hier nicht ausnutzbar, aber eine Lücke in der Verteidigungstiefe. |
Die Ausführung von JavaScript wurde ausgeschlossen, nicht angenommen. Drei getrennte Durchläufe haben nach einer Eskalation zu JavaScript gesucht und keine gefunden. DOM Clobbering scheitert daran, dass jede in Frage kommende Element-ID (mx_Dialog_Container, mx_ContextualMenu_Container und die übrigen) bereits vor dem Injection-Punkt in der index.html existiert. document.getElementById liefert daher den vorhandenen Knoten, und die window.mx*-Singletons werden beim Laden der Module initialisiert, bevor EmbeddedPage rendert. Es ist kein Script-Gadget erreichbar: React 19 mountet über createRoot statt per Hydration, wasm-unsafe-eval setzt bereits laufendes JavaScript voraus, die Origin liefert keinen JSONP- oder reflektierenden Endpunkt, und das gebündelte webpack (5.107.1 in der geprüften Version) ist gegen base-Tag-Clobbering gepatcht (CVE-2024-43788, upstream behoben in 5.94.0). Ein <meta http-equiv>-Element bleibt wirkungslos, wenn es über innerHTML eingefügt wird. Die postMessage-Handler prüfen ihre Origin (ScalarMessaging) beziehungsweise ihre event.source (SSO und Fallback-Auth), und auf der Startseite ist keine ClientWidgetApi-Instanz aktiv.
Reichweite. Das well-known-Dokument wird ausschließlich vom eigenen Homeserver gelesen, über matrixClient.getClientWellKnown(). Well-known-Daten werden nicht föderiert, ein bösartiger Server auf der anderen Seite eines föderierten Raums erreicht also keine Clients, die sich anderswo authentifizieren. Der Angreifer ist der Betreiber des bereits gewählten Servers oder wer diesen Server übernommen hat.
Am 2026-04-01 an Element gemeldet. Der Fix wurde am 2026-06-15 mit Pull Request #33842 übernommen und mit 1.12.22 ausgeliefert: Die eingebettete Seite wird jetzt über den gemeinsamen Helper sanitizedHtmlNode gerendert statt über dangerouslySetInnerHTML.
Auswirkung
- Ein bösartiger Homeserver-Betreiber, oder wer einen Homeserver übernommen hat, kann angreiferkontrolliertes Markup auf der Startseite jedes Element-Web-Clients platzieren, der sich gegen diesen Server authentifiziert. Die Startseite ist die Standardansicht nach Anmeldung und Registrierung und bleibt über den Home-Button erreichbar. Der eingeschleuste Inhalt ist damit dauerhaft präsent und nicht auf einen einzelnen Moment beschränkt.
- Die Ausführung von JavaScript ist blockiert, Nachrichten, Access Token und Schlüsselmaterial bleiben unerreichbar. Was bleibt, ist Credential-Phishing.
frame-src *erlaubt ein bildschirmfüllendes Iframe von beliebiger Origin, und ein Formular in diesem Iframe hat einen eigenen Browsing-Context, sodassform-action 'self'der Elternseite nicht bestimmt, wohin es sendet. Ein wie der umgebende Client gestalteter Dialog "Sitzung abgelaufen" nimmt das Passwort entgegen und sendet es an den Angreifer, innerhalb einer Anwendung, der die betroffene Person bereits vertraut. Wir haben das durchgängig gegen Element Web v1.11.96 bestätigt. img-src *erlaubt zusätzlich Tracking-Pixel, die melden, wann und wie oft eine bestimmte Person den Client öffnet, undstyle-src 'unsafe-inline'lässt das eingeschleuste Markup die Oberfläche ringsum umgestalten.
Abhilfe
Aktualisieren Sie Element Web oder Element Desktop auf 1.12.22 oder höher. Der Fix rendert die eingebettete Seite über den gemeinsamen Helper sanitizedHtmlNode, der genau die Tags entfernt, auf denen die Injection beruht. Deployments, die nicht sofort aktualisieren können, sollten embedded_pages.home_url explizit in der config.json setzen; der Resolver zieht den homeserver-kontrollierten well-known-Schlüssel dann gar nicht erst heran. Unabhängig von der Version entfernt eine Einschränkung von frame-src auf 'self' plus die tatsächlich genutzten Widget- und Call-Origins das Phishing-Primitive, und base-uri 'none' schließt eine Lücke in der Verteidigungstiefe, da base-uri nicht auf default-src zurückfällt. Für alle, die einen Client nutzen, den sie nicht selbst administrieren: Die Startseite hat keinen legitimen Grund, nach einem Passwort zu fragen. Behandeln Sie jede dort erscheinende Anmeldeaufforderung als verdächtig, bis der Client aktualisiert ist.
Checkliste für Betreiber
Auf Element Web oder Element Desktop 1.12.22 oder höher aktualisieren.
Jede frühere Version rendert die eingebettete Startseite ungefiltert. Der Fix liegt in Pull Request #33842.
embedded_pages.home_url in der eigenen Konfiguration setzen.
getHomePageUrl()zieht das well-known des Homeservers nur heran, wenn die Deployment-Konfiguration den Schlüssel offen lässt. Ihn in derconfig.jsonzu setzen nimmt den Homeserver in jeder Version aus dem Vertrauenspfad der Startseite. Prüfen Sie dieconfig.json, die Sie tatsächlich ausliefern, nicht das Beispiel.Die CSP des Deployments verschärfen.
frame-src *macht aus der Markup-Injection erst eine Phishing-Oberfläche, weil ein Formular in einem fremden Iframe nicht anform-action 'self'der Elternseite gebunden ist. Schränken Sie die Direktive auf'self'plus die tatsächlich genutzten Widget- und Call-Origins ein und ergänzen Siebase-uri 'none', das nicht aufdefault-srczurückfällt.Forks und eigene Startseiten prüfen.
Produkte auf Basis der Element-Web-Codebasis erben sowohl das ungefilterte Rendern als auch den well-known-Fallback. Wenn Sie einen Fork pflegen oder eine eigene Startseite ausliefern, prüfen Sie, ob der Fix übernommen ist und ob Ihr Deployment
home_urlfest setzt.
Bewertung im Detail
.well-known/matrix/client-Antwort. Kein Timing, keine Race Condition, keine Vorbereitung pro Ziel.PR:HErfordert administrative Kontrolle über den Homeserver, gegen den sich die betroffene Person authentifiziert, als Betreiber oder nach dessen Kompromittierung.UI:NDer Client lädt und rendert die Startseite nach der Anmeldung von sich aus.S:CDie verwundbare Komponente ist der Web-Client. Das eingeschleuste Iframe läuft in einem Browsing-Context, den die form-action des Clients nicht mehr einschränkt, und die erbeuteten Credentials authentifizieren über die rendernde Komponente hinaus.C:LGeladene Ressourcen verraten, wann eine bestimmte Person den Client geöffnet hat. Nachrichteninhalte und Schlüsselmaterial bleiben hinter der CSP.I:HDer Angreifer kontrolliert das Markup in einer vertrauten Oberfläche der Anwendung vollständig, bis hin zum bildschirmfüllenden Overlay.A:NKeine Auswirkung auf die Verfügbarkeit.Element hat das Advisory als Moderate eingestuft. Der Unterschied liegt in der Scope-Metrik: derselbe Vektor mit S:U ergibt 5.5. Wir bewerten S:C, weil die im Phishing-Dialog erbeuteten Credentials nicht auf die Komponente beschränkt sind, die den Dialog rendert. Beide Präzedenzfälle bewerten S:C an derselben Vertrauensgrenze des Clients: CVE-2024-42347 (ein Homeserver aktiviert URL-Vorschauen in verschlüsselten Räumen, 7.7) und CVE-2023-30609 (HTML-Injection in den Suchergebnissen des matrix-react-sdk, 5.4).
Referenzen
- GHSA-wrcp-5v3v-3j6v (Element)
- CVE-2026-55850 (NVD)
- Element Web v1.12.22 Release
- Element-Web-Pull-Request #33842 (Fix)
- matrix-react-sdk-Pull-Request #7790 (Ursprung des well-known-Fallbacks)
- Element-Web-Repository
- CVE-2024-42347 (NVD, Präzedenzfall für S:C)
- CVE-2023-30609 (NVD, Präzedenzfall für S:C)
- Verwandt: Absturz von Element X Android durch einen manipulierten OIDC-Redirect-Intent
So können wir helfen
Wer wir sind
Die Sicherheitsforscher hinter diesem Sicherheitshinweis.

Dr. rer. nat. Simon Weber
Senior Pentester & MedSec-Forscher
Ich evaluiere Ihr SaMD mit derselben branchenprägenden Sicherheitsexpertise, die ich dem BAK MV für die Überarbeitung des B3S-Standards beigetragen habe.
- Promotion über Krankenhaus-Cybersicherheit
- Kritische Schwachstellen in Krankenhaussystemen gefunden
- Alumni der THB MedSec-Forschungsgruppe
- gematik Security Hero

Dipl.-Inf. Volker Schönefeld
Senior Application Security Expert
Als ehemaliger CTO und Entwickler, der zum Pentester wurde, arbeite ich mit Ihrem Team zusammen, um Schwachstellen aufzudecken und Lösungen zu finden, die zu Ihrer Architektur passen.
- 20+ Jahre als CTO, 50+ Mio. App-Downloads
- Architektur und Absicherung großer IoT-Flotten
- Certified Web Exploitation Specialist
- gematik Security Hero
Penetrationstest gesucht?
Machine Spirits ist spezialisiert auf Sicherheitsbewertungen für Medizinprodukte und Gesundheits-IT. Von MDR-Penetrationstests bis C5-Cloud-Compliance helfen wir MedTech-Unternehmen, regulatorische Anforderungen zu erfüllen.
