Markdown-XSS-Schwachstellen: Sichere Schritte zur Sanitierung von Rich‑Text
Markdown-XSS-Schwachstellen können sich in Kommentaren und Notizen verbergen. Erfahren Sie sichere HTML-Sanitierung, Beschränkungen für Embeds und wie Sie reale Payloads vor dem Launch testen.

Warum Markdown und Rich-Text zu einer Sicherheitslücke werden können
Markdown und Rich-Text wirken harmlos, weil sie wie normales Schreiben aussehen. Viele Apps machen jedoch dasselbe im Hintergrund: Sie nehmen, was ein Nutzer getippt hat, wandeln es in HTML um und rendern dieses HTML im Browser einer anderen Person.
Genau dieser letzte Schritt ist problematisch. Wenn ein Angreifer HTML einschleusen kann, das der Browser als Code behandelt, kann er JavaScript in der Sitzung eines anderen Nutzers ausführen. Das ist XSS (cross-site scripting) ganz praktisch: Das Skript des Angreifers läuft so, als käme es von Ihrer Seite und mit dem Zugriff des Opfers.
Kommentare, Notizen und Support-Antworten sind ein häufiger Angriffsweg, weil sie einfach zu posten sind (oft ohne Prüfung), vielen Leuten gezeigt werden (Admins, Teammitglieder, Kunden) und gespeichert sowie später erneut gerendert werden. Ein schlechter Eintrag kann Monate lang Schaden anrichten.
Das Schwierige ist, dass Markdown- und Rich-Text-Editoren häufig HTML erzeugen, das Sie nicht erwartet haben. Ein „einfaches“ Einfügen aus Google Docs kann seltsame Tags und Attribute mitbringen. Manche Markdown-Setups erlauben rohes HTML absichtlich. Manche Editoren geben Attribute aus, mit denen Sie nie gerechnet haben. Wenn Ihre App diese Ausgabe direkt rendert, können Sie Markdown-XSS-Schwachstellen bekommen, selbst wenn die UI harmlos aussieht.
Ein realistisches Beispiel: Ein Gründer fügt eine Notizfunktion hinzu, in der Teammitglieder Schnipsel einfügen und Text formatieren können. Jemand fügt Inhalte ein, die einen Event-Handler wie onerror an einem Bild enthalten. Wenn Ihr Renderer das behält, wird bei jedem Öffnen der Notiz durch einen Admin die Payload ausgeführt.
Inhaltsdarstellung ist ein Sicherheitsmerkmal, nicht nur eine Frage der Formatierung.
Die grundlegenden XSS-Risiken bei nutzergenerierten Inhalten
XSS passiert, wenn Ihre App Nutzereingaben so anzeigt, als wären sie vertrauenswürdiger Seiteninhalt. Bei Markdown und Rich-Text steigt das Risiko, weil Sie Eingaben oft in HTML umwandeln und dieses HTML dann im Browser anderer darstellen.
Bei Kommentaren, Notizen und Profilen ist das größte Problem meist Stored XSS. Jemand postet einen „Kommentar“, der heimliches HTML oder JavaScript enthält. Ihr Server speichert ihn, und jede Person, die den Thread betrachtet, führt den Code des Angreifers aus.
Reflektiertes XSS ist die andere häufige Form: Die Payload wird sofort zurückgeworfen (oft über eine URL oder ein Suchfeld). Das ist auch relevant, aber Stored XSS fügt sich über die Zeit immer wieder.
Die Opfer sind nicht nur zufällige Nutzer. Mitarbeitende sind oft stärker gefährdet, weil sie mehr Inhalte sehen: Moderatoren, Support-Agenten, Admins, die Dashboards öffnen, die Nutzerbeiträge zeigen.
Wenn ein Stored XSS landet, kann ein Angreifer Session-Cookies oder Access-Tokens stehlen, private Daten lesen, die in der UI angezeigt werden (Nachrichten, E-Mails, Abrechnungsdaten), Aktionen im Namen des Opfers ausführen (posten, löschen, Einstellungen ändern) oder Nutzer mit gefälschter UI täuschen (Phishing innerhalb Ihrer Seite).
„Nur interne Nutzer haben Zugriff“ ist weiterhin riskant. Interne Konten sind oft mächtiger, Passwortwiederverwendung kommt vor und sie werden von anderen Systemen vertraut. Ein bösartiger Kommentar kann schnell von einem Low-Privilege-Nutzer auf ein Staff-Konto überspringen.
Ein einfaches Beispiel: Ein Nutzer postet eine scheinbar normale Notiz, die jedoch einen in erlaubtem HTML versteckten Event-Handler enthält. Wenn ein Support-Mitarbeiter die Notiz erweitert, läuft die Payload und schickt stillschweigend seine Session an den Angreifer. So werden Markdown-XSS-Schwachstellen zu echten Account-Übernahmen.
Wo unsicheres HTML hereinschlüpft
Die meisten Teams erwarten Probleme nur, wenn sie rohes HTML erlauben. Die Überraschung ist, dass Sie Markdown-XSS-Schwachstellen auch dann bekommen können, wenn Nutzer nur „normales“ Markdown tippen.
Markdown-Features werden in HTML kompiliert, das der Browser fröhlich interpretiert, wenn Sie es nicht bereinigen. Links und Bilder sind die großen Baustellen: Ein harmlos aussehendes [text](...) oder  wird zu einem \\u003ca\\u003e- oder \\u003cimg\\u003e-Tag. Gefährlich ist oft nicht der Tag selbst, sondern das URL-Schema und die Attribute, die darin landen.
Einige Markdown-Parser erlauben standardmäßig auch rohe HTML-Blöcke. Das bedeutet, ein Nutzer kann \\u003cimg onerror=...\\u003e oder \\u003csvg\\u003e direkt in einen Kommentar einfügen, es passiert ungehindert durch und läuft beim Rendern. Selbst wenn Sie denken „wir escapen HTML“, prüfen Sie Ihre Parser-Einstellungen und Plugins, die das wieder aktivieren.
Rich-Text-Editoren können schlimmer sein, weil sie HTML erzeugen, das auf den ersten Blick harmlos wirkt. Ein kurzer fett formatierter Satz kann zusätzliche Attribute, Inline-Stile und seltsame Tags enthalten, die Ihr Sanitizer korrekt verstehen muss. Ein häufiger Fehler ist, „sichere“ Tags zu erlauben, aber gefährliche Attribute wie Event-Handler (onload, onclick) oder URL-haltige Attribute zu übersehen, die javascript:-Payloads verbergen können.
Copy-Paste aus Google Docs oder Notion ist eine häufige Quelle für unordentliches Markup. Nutzer fügen formatierten Text ein, und plötzlich haben Sie verschachtelte Spans, Inline-CSS und Metadatenattribute, die nie Teil Ihres Plans waren. Dieses zusätzliche HTML erhöht die Chance auf einen Bypass oder dass Ihr Sanitizer das Rendering unvorhersehbar zerstört.
Bei der Überprüfung konzentrieren Sie sich auf die Einstiegspunkte, die wiederholt Probleme machen: rohes HTML aktiviert im Markdown-Parser; Links oder Bilder, bei denen das URL-Schema nicht eingeschränkt ist; „erlaubte Attribute“-Listen, die zu breit sind; Plugins, die HTML-Features hinzufügen (Tabellen, Erwähnungen, Embeds); und Einfügepfade, die komplettes HTML statt Plain-Text akzeptieren.
Wählen Sie ein sicheres Inhaltsmodell, bevor Sie einen Sanitizer wählen
Die meisten Stored-XSS-Bugs beginnen mit einer Unstimmigkeit: Sie dachten, Sie speichern „Kommentare“, tatsächlich speichert Ihr System Mini-Webseiten. Bevor Sie eine Bibliothek auswählen, entscheiden Sie, was Nutzer ausdrücken dürfen.
Eine praktische Herangehensweise an Markdown-XSS-Schwachstellen ist, ein Inhaltsmodell zu wählen und dabei zu bleiben:
- Plain Text: am sichersten und einfachsten. Sie können Basics wie Zeilenumbrüche und einfache Autolinks unterstützen.
- Begrenztes Markdown: gut für die meisten Produkte. Erlauben Sie Formatierung (fett, kursiv, Listen, Code), aber halten Sie es vorhersehbar.
- Volles Rich-Text (HTML-ähnlich): höchstes Risiko. Wählen Sie das nur, wenn Sie wirklich komplexe Layouts brauchen.
Sobald Sie sich entschieden haben, schreiben Sie Ihre Regeln als Allowlist nieder. Für begrenztes Markdown ist eine typische sichere Menge an Elementen: p, strong, em, ul, ol, li, code, pre und a. Halten Sie die Liste absichtlich kurz.
Seien Sie auch explizit bei dem, was niemals erlaubt ist. Offensichtliche Kandidaten sind script, iframe, object, embed und style. Viele „normale“ Tags können jedoch abhängig von Ihrer Konfiguration gefährlich sein, besonders alles, was entfernbare Inhalte lädt oder die Seite beeinflusst.
Attribute brauchen die gleiche Behandlung. Links sollten zum Beispiel nur href erlauben, und alles, was wie ein Event-Handler aussieht (onclick, onerror und Konsorten), lehnen Sie ab.
Wie man HTML sicher sanitisiert (ohne alles kaputt zu machen)
Der sicherste Weg, Markdown-XSS-Schwachstellen zu vermeiden, ist davon auszugehen, dass Nutzerinhalte und Ihre Abhängigkeiten sich im Laufe der Zeit ändern werden. Ihr Markdown-Parser wird aktualisiert, Browser ändern sich, und „harmlos“ erscheinende Tags können neues Verhalten bekommen.
Deshalb ist es riskant, nur beim Speichern zu sanitizen. Sanitizen Sie auch beim Rendern, damit alte Inhalte nach einem Abhängigkeits-Update oder einer Konfigurationsänderung weiterhin sicher bleiben.
Eine praktische Regel: Bevorzugen Sie eine Allowlist. Blocklisten übersehen oft Randfälle (neue Tags, seltsame Attribute, Browser-Eigenheiten). Eine Allowlist beantwortet eine klare Frage: „Was erlauben wir in Kommentaren?“ Meist ist das grundlegende Formatierung, einfache Links und nichts, was Code ausführen kann.
Bevor Sie sanitizen, normalisieren Sie das, was Sie sanitizen. Angreifer nutzen Tricks wie kodierte Zeichen und ungewöhnliche Leerzeichen, um Filter zu umgehen. Dekodieren Sie Entities, normalisieren Sie Unicode und parsen Sie in einen echten HTML-Baum (nicht mit Regex). Dann führen Sie den Sanitizer auf dieser normalisierten Repräsentation aus, damit er nicht durch alternative Schreibweisen hereingelegt werden kann.
Ein Workflow, der die meisten Brüche vermeidet, sieht so aus:
- Markdown mit einer vertrauenswürdigen Bibliothek zu HTML parsen.
- Das HTML normalisieren und dekodieren (Entities, Unicode, Attributabstände).
- Mit einer Allowlist sanitizen (Tags + Attribute + URL-Schemata).
- Die bereinigte Ausgabe rendern und zusätzlich eine sichere Content Security Policy setzen.
- Inhalte, die stark gekürzt werden, protokollieren oder markieren (oft ein Zeichen für Scans).
Halten Sie Ihre Sanitizer-Regeln an einem Ort und behandeln Sie sie wie Code. Versionieren Sie die Konfiguration, führen Sie ein kurzes Changelog und schreiben Sie ein paar Tests, die prüfen, was behalten bzw. entfernt wird. Beispiel: Wenn Sie später \\u003cimg\\u003e erlauben wollen, ändern Sie die Allowlist, aktualisieren die Tests und sanitizen erneut zur Render-Zeit, damit ältere Kommentare nicht plötzlich gefährlich werden.
Lockdown für Links, Bilder und Styling
Links, Bilder und Styling sind die Stellen, an denen „sicheres“ Markdown oft zu Stored XSS wird. Selbst wenn Sie HTML-Tags sanitizen, müssen Sie jede URL und jeden Stilwert als untrusted behandeln.
Fangen Sie bei Links an. Ein normal aussehender Anker kann zum Angriff werden, wenn Sie riskante URL-Schemata wie javascript: oder data: erlauben. Die einfachste Regel: Erlauben Sie nur https: (und vielleicht http: für interne oder Dev-Tools) und lehnen Sie alles andere ab. Normalisieren und dekodieren Sie vorher, weil Angreifer Tricks wie gemischte Groß-/Kleinschreibung und kodierte Zeichen nutzen.
Wenn Sie Nutzerlinks in einem neuen Tab mit target="_blank" öffnen, härten Sie das ab. Ohne passende rel-Werte kann die neue Seite die ursprüngliche Registerkarte steuern (Tabnabbing). Machen Sie das zum Standardverhalten Ihres Renderers statt es den Autoren zu überlassen.
Bilder sind nicht „nur Bilder“. Ein src kann zu Tracking-Pixeln, internen Netzwerkressourcen oder seltsamen Schemata zeigen. Wenn Sie Bilder erlauben, beschränken Sie die src-Schemata und erwägen Sie, Bilder zu proxyen, damit der Browser sie nicht direkt vom Angreifer-Server lädt.
Styling ist die stille Gefahr. Auch wenn CSS kein Skript ausführt, kann es Warnungen verbergen, Buttons verschieben oder eine gefälschte Login-Box echt aussehen lassen. Für Kommentar-Sicherheit bevorzugen Sie eine winzige Allowlist für einfache Formatierung (fett, kursiv, Listen) und vermeiden es, Nutzern beliebiges CSS setzen zu lassen.
Praktische Regeln:
- Erlauben Sie nur
https:(optionalhttp:) inhrefundsrc; blockieren Siejavascript:,data:,file:undblob:. - Wenn
target="_blank"erlaubt ist, erzwingen Sierel="noopener noreferrer". - Inline-
styleentfernen und\\u003cstyle\\u003ekomplett blockieren. - Bildunterstützung minimal halten oder Bilder serverseitig proxyen und cachen.
- Klare Limits setzen: maximale URL-Länge, maximale Anzahl Attribute, maximale Elemente.
Beispiel: Eine Notiz-App rendert Markdown zu HTML und erlaubt Bilder. Ein Angreifer postet ein „hilfreiches Diagramm“, das von seinem Server lädt, jede Ansicht protokolliert und CSS nutzt, um den echten „Notiz löschen“-Button unter einer gefälschten „Erneut authentifizieren“-Aufforderung zu verstecken. Markdown-XSS-Schwachstellen zu beheben bedeutet, diese Risiken als Kernprodukt-Risiken zu behandeln, nicht als Randfälle.
Embeds: der schnellste Weg, unbeabsichtigt Skript-Ausführung zu erlauben
Embeds wirken harmlos, weil sie wie „nur ein Video“ oder „nur ein Tweet“ aussehen. Tatsächlich sind sie einer der schnellsten Wege, um Nutzereinhalte in Stored XSS zu verwandeln, besonders wenn Markdown oder Rich-Text rohes HTML erlauben. Viele Markdown-XSS-Vorfälle beginnen mit einer Ausnahme für iframes.
Wenn Sie Embeds unterstützen, entscheiden Sie im Voraus, welche Anbieter erlaubt sind und was „Embed“ in Ihrer App bedeutet. „Beliebiges iframe“ ist kein Feature. Es ist ein Sicherheitsloch.
Ein sichereres Muster: Nutzer fügen eine normale URL ein, Ihr Server prüft sie gegen eine Allowlist und Ihr Server erzeugt das finale Embed-HTML. Akzeptieren Sie nicht benutzerdefinierte iframe-Tags oder beliebige Attribute wie srcdoc, onload oder allow.
Regeln, die Embeds nützlich halten, ohne Angreifern eine Angriffsfläche zu geben:
- Erlauben Sie nur spezifische Anbieter (nach Hostname und Pfadmuster) und blockieren Sie alles andere.
- Generieren Sie Embed-HTML serverseitig aus einer sauberen Vorlage, nicht aus Nutzer-HTML.
- Deaktivieren Sie inline-iframes generell in Kommentaren/Notizen, sofern kein starker Grund vorliegt.
- Wenn Sie iframes erlauben müssen, setzen Sie feste Größenlimits und ein striktes
sandbox. - Entfernen Sie alle Event-Handler und riskanten Attribute; erlauben Sie niemals
javascript:-URLs.
Selbst mit Sandboxing laden Embeds Drittinhalte. Behandeln Sie sie wie eine separate Grenze.
Testen Sie reale XSS-Payloads vor dem Rollout
Sanitizer sehen in einer Demo oft gut aus und versagen dann bei seltsamen Eingaben, die echte Nutzer erzeugen. Bevor Sie Kommentare oder Notizen ausrollen, führen Sie eine kleine Menge wiederholbarer Tests durch, die versuchen, Ihren Renderer und Ihre HTML-Sanitizer-Regeln zu brechen.
Starten Sie mit drei Rollen und drei Ansichten. Nutzen Sie einen normalen Nutzer, der Inhalte posten kann, und verifizieren Sie dann, was ein Moderator sieht und was ein Admin sieht. Stored XSS tritt oft nur auf, wenn jemand anderes die Seite lädt, besonders in Dashboards, Moderations-Queues, E-Mail-Vorschauen oder „Letzte Aktivitäten“-Panels.
Verwenden Sie eine kurze Suite von Payloads, die gängige Bypass-Stile abdecken (verlassen Sie sich nicht auf ein oder zwei offensichtliche). Zum Beispiel: kodierte Zeichen (HTML-Entities, gemischte Groß-/Kleinschreibung in Attributen), fehlerhafte oder ungeschlossene Tags (um den Parser zu verwirren), verschachtelte Tags (harmlos scheinendes Außentag, gefährliches Innentag), gefährliche URLs in Links (javascript: oder data:) und Event-Handler-Attribute (wie onerror) an jedem Tag, das Ihr Sanitizer erlaubt.
Halten Sie Ihre Tests realistisch: Der Inhalt sollte weiterhin gerendert werden, wenn er harmlos ist, darf aber niemals Code ausführen. Eine gute Überprüfung ist: „Wird der Kommentar als Text oder sicheres Markup angezeigt, ohne Popups, Weiterleitungen, Netzwerkaufrufe oder unerwartete UI-Änderungen?"
Prüfen Sie außerdem das Verhalten an allen Stellen, an denen derselbe Inhalt angezeigt wird. Ein Sanitizer, der im Editor greift, aber nicht in der E-Mail-Benachrichtigung, oder der in der Kommentarseite greift, aber nicht im Admin-Table, ist ein klassischer Stored-XSS-Pfad.
Häufige Fehler, die zu Stored XSS führen
Stored XSS entsteht meist, wenn Sie annehmen, Nutzerdaten seien „bereits sicher“, weil sie aus einem ausgefeilten Editor stammen. Ein WYSIWYG kann dennoch gefährliches HTML ausgeben (oder damit getäuscht werden), und Markdown-Parser erlauben oft überraschende Randfälle. Deshalb tauchen Markdown-XSS-Schwachstellen selbst in Produkten auf, die „nur Kommentare“ unterstützen.
Eine häufige Falle ist, nur im Browser zu sanitizen. Client-seitige Bereinigung lässt sich leicht umgehen mit direkten API-Anfragen oder dem Replay einer Anfrage von einem anderen Gerät. Wenn der Server unsanitized Content speichert, haben Sie ein Stored-XSS-Problem, das überall dort zuschlägt, wo der Inhalt angezeigt wird.
Ein weiterer Fehler ist, rohes HTML im Markdown zu erlauben, um Features am Laufen zu halten (benutzerdefinierte Buttons, iframes, ausgefallenes Styling). Diese Wahl verwandelt Ihre Markdown-Funktion still und leise in eine HTML-Hosting-Funktion. Selbst wenn Sie offensichtliche Tags wie \\u003cscript\\u003e entfernen, können Angreifer Event-Handler (onerror), raffinierte URLs oder SVG-basierte Payloads nutzen, abhängig davon, was Sie erlauben.
Eine große Quelle von Vorfällen sind „sekundäre Renderer“, die man vergisst. Möglicherweise sanitizen Sie die Hauptkommentarseite, aber nicht die Admin-Ansicht, nicht die E-Mail-Vorlage und nicht den Export-zu-PDF-Flow.
Wiederkehrende Fehlermuster sind: Editor-Ausgabe als vertrauenswürdig behandeln und unverändert speichern; nur client-seitig reinigen und dann den rohen Inhalt serverseitig speichern; unterschiedliche Sanitizer (oder Allowlists) an verschiedenen Stellen verwenden; denselben gespeicherten Inhalt in HTML, E-Mail und Admin-Tools rendern, ohne erneut zu prüfen; und rohes HTML in internen Dashboards loggen oder anzeigen.
Beispiel: Ein Nutzer postet einen „harmlosen“ Kommentar mit einem Bild, das ein manipuliertes Attribut enthält. Die öffentliche Seite ist sicher, aber das Admin-Panel benutzt einen anderen Renderer für die Moderation, und die Payload läuft, wenn das Personal die Queue öffnet.
Schnell-Checkliste für Kommentare und Notizen
Kommentare und Notizen sind der Ort, an dem Markdown-XSS-Schwachstellen meist zuerst auftauchen, weil sie harmlos wirken und schnell ausgerollt werden. Bevor Sie sie für echte Nutzer freischalten, machen Sie eine kurze Sicherheitsprüfung.
Checkliste, die die meisten Stored-XSS-Probleme abfängt:
- Bestätigen Sie, dass rohes HTML im Markdown entweder komplett deaktiviert ist oder nach dem Rendern bereinigt wird. Verlassen Sie sich nicht darauf, „der Editor erzeugt es nicht“.
- Verwenden Sie eine Allowlist für Tags und Attribute. Blockieren Sie alle Event-Handler wie
onclickund vermeiden Sie riskante Attribute wiestyle, es sei denn, Sie filtern sie sehr strikt. - Validieren und normalisieren Sie URLs in
hrefundsrc. Lehnen Siejavascript:unddata:-Schemata (und alles, was Sie nicht explizit unterstützen) ab. - Sperren Sie Embeds. Wenn Sie iframes oder „Video-Link einfügen“-Features erlauben, setzen Sie strikte Regeln und ziehen Sie in Erwägung, sie als einfache Links darzustellen.
- Prüfen Sie jede Stelle, an der Inhalte angezeigt werden, nicht nur die Hauptseite: Admin-Ansichten, Benachrichtigungs-E-Mails, Mobile Webviews, Exporte (PDF/Druck) und interne Dashboards.
Nach der Checkliste führen Sie einen kleinen Smoke-Test mit realen Payloads durch. Das Ziel ist nicht, ein Alert-Box-Popup zu sehen. Es geht darum zu bestätigen, dass Ihre Ausgabe überall inaktiv bleibt.
Probieren Sie ein paar bekannte bösartige Eingaben (script-Tags, Event-Handler-Attribute und seltsame URLs) und bestätigen Sie, dass sie als Text gerendert oder entfernt werden. Verifizieren Sie die gespeicherte Version in Ihrer Datenbank ist sicher, nicht nur die Vorschau. Wiederholen Sie den Test auf der Admin-Seite, da Admins oft mehr Inhalte sehen und höhere Rechte haben.
Beispiel-Szenario: ein einfaches Kommentar-Feature, das zu XSS wird
Ein Gründer bringt ein kleines Feedback-Widget heraus: Nutzer können Markdown-Kommentare auf jeder Seite hinterlassen. Es fühlt sich sicher an, weil „es ist nur Text“, und die Vorschau sieht gut aus.
Um Rich-Text zu unterstützen, konvertiert die App Markdown zu HTML und rendert es im Admin-Dashboard. Jemand hat außerdem „nice to have“-Funktionen hinzugefügt: Autolink-URLs, Bildunterstützung und ein schnelles Embed für Videos.
Ein Angreifer postet einen Kommentar, der im Widget normal aussieht, z. B. ein Bug-Report mit einem Link. Aber das Markdown enthält HTML, das der Konverter durchlässt, oder es versteckt eine Payload in einem erlaubten Attribut. Für den Angreifer passiert nichts Auffälliges. Später, wenn ein Admin das Dashboard öffnet, läuft der Kommentar-Code im Browser des Admins.
Was dann bricht, ist selten subtil. Der Angreifer kann die Admin-Session stehlen und das Konto übernehmen, private Feedbacks oder interne Notizen lesen, die auf derselben Seite angezeigt werden, und Einstellungen ändern (z. B. Webhooks oder API-Keys) mit den Rechten des Admins.
Ein sicheres Design hätte das vor dem Rollout verhindert. Behandeln Sie Kommentare als untrusted Daten und sperren Sie, was „Rich-Text“ wirklich bedeutet: Markdown in ein begrenztes HTML-Subset konvertieren, mit einer strikten Allowlist sanitizen, riskante Attribute (insbesondere Event-Handler und gewisse URL-Schemata) entfernen oder umschreiben, Embeds standardmäßig deaktivieren (oder nur eine kleine Menge von Anbietern mit harten Regeln erlauben) und reale Payloads in der tatsächlichen Admin-Ansicht testen, nicht nur im öffentlichen Widget.
Nächste Schritte: sicher ausliefern und eine zweite Meinung einholen
Wenn Sie Kommentare oder Notizen ohne Überraschungen ausliefern wollen, behandeln Sie Rich-Text als Feature, das einen kleinen Sicherheitsplan braucht, nicht als schnelle UI-Ergänzung.
Beginnen Sie damit, Entscheidungen niederzuschreiben, die Sie konsistent in der App halten können: Wählen Sie ein Inhaltsmodell (Plain Text, Markdown ohne HTML oder bereinigtes HTML), definieren Sie erlaubte Elemente und Attribute (streng sein; die meisten Apps brauchen sehr wenig), sperren Sie Embeds im Voraus (oder überspringen Sie sie bis Sie Zeit haben), erstellen Sie eine kleine XSS-Payload-Suite, die zu Ihren Features passt (Links, Bilder, Code-Blöcke, Erwähnungen), und entscheiden Sie, wo Sanitierung stattfindet (serverseitig ist die Quelle der Wahrheit).
Fügen Sie dann ein Release-Gate hinzu. Das Ziel ist einfach: Kein Deploy geht raus, bevor Ihre gespeicherten Payloads in der realen UI sicher rendern. Das fängt Probleme, die Unit-Tests nicht sehen, wie ein client-seitiges Markdown-Plugin, das still HTML aktiviert.
Ein Release-Gate kann leichtgewichtig bleiben. Führen Sie die Payload-Suite gegen Create-, Edit- und Preview-Flows aus. Verifizieren Sie die Ausgabe im Browser, nicht nur in API-Antworten. Bestätigen Sie, dass dieselben Regeln überall gelten, wo Nutzerdaten erscheinen (Feed, E-Mail, Admin-Views). Fügen Sie für jeden gefundenen Bug einen Regressionstest hinzu, damit er behoben bleibt.
Wenn Ihre App generiert wurde oder stark durch Tools wie Lovable, Bolt, v0, Cursor oder Replit unterstützt wurde, gehen Sie davon aus, dass Defaults inkonsistent sein können. Ein Bildschirm könnte einen sicheren Renderer nutzen, während ein anderer eine andere Bibliothek oder einen Vorschau-Modus nutzt, der rohes HTML erlaubt.
Wenn Sie eine einfache zweite Meinung wollen: FixMyMess (fixmymess.ai) konzentriert sich auf die Diagnose und Reparatur von AI-generierten Codebasen, inklusive unsicherer Markdown- und Rich-Text-Rendering-Pfade, und bietet ein kostenloses Code-Audit an, um Stored-XSS-Risiken und verwandte Probleme vor dem Rollout zu identifizieren.
Häufige Fragen
Warum kann Markdown ein Sicherheitsrisiko sein, wenn es „nur Text“ ist?
Markdown wird meist in HTML umgewandelt, und dieses HTML wird im Browser anderer Personen gerendert. Wenn Teile der Eingabe als ausführbares HTML oder gefährliche Attribute erhalten bleiben, kann das zu Stored XSS werden – selbst wenn der Editor auf den ersten Blick wie „nur Text“ wirkt.
Welche Art von XSS ist bei Kommentaren und Notizen am häufigsten?
Meistens ist es Stored XSS: ein bösartiger Kommentar oder eine Notiz wird gespeichert und führt später aus, wenn jemand anderes sie ansieht. Das ist gefährlicher als reflektiertes XSS, weil es Admins, Support und Kunden über längere Zeit treffen kann.
Wo schleicht sich unsicheres HTML normalerweise bei Markdown oder Rich-Text ein?
Raw-HTML-Unterstützung ist der häufigste Grund. Außerdem können Links und Bilder gefährlich sein, wenn Sie URL-Schemata nicht einschränken. Rich-Text-Einfügungen bringen oft unerwartete Tags und Attribute mit, die Ihr Sanitizer nicht korrekt verarbeitet.
Welches Inhaltsmodell ist für Benutzerkommentare am sichersten?
Standardmäßig zu eingeschränktem Markdown greifen: grundlegende Formatierung und Links erlauben, alles andere ablehnen. Halten Sie die erlaubte Menge klein und explizit, damit Sie nicht versehentlich Mini-Webseiten in Kommentaren hosten.
Sollte ich beim Speichern, beim Rendern oder beides sanitieren?
Sanitieren Sie auch zur Render-Zeit, nicht nur beim Speichern. Render-Zeit-Sanitierung schützt alte Inhalte, falls sich Ihr Parser, Ihre Konfiguration oder Browserverhalten ändern und gespeicherte Inhalte plötzlich riskant werden.
Wie mache ich Markdown-Links gegen `javascript:`-Tricks sicher?
Erlauben Sie nur sichere Schemata wie https: (oder in kontrollierten Fällen http:) nach Decodierung und Normalisierung. Blockieren Sie javascript:, data:, file: und andere unerwartete Schemata – sie sind ein häufiger Weg, Ausführung oder seltsames Verhalten in „normalem“ Markdown zu schmuggeln.
Sind Bilder in Markdown gefährlich oder nur lästig?
Wenn Sie Bilder unterstützen müssen, behandeln Sie src als untrusted: Schemata einschränken und überlegen, Bilder zu proxyen, damit Browser nicht direkt angreifergesteuerte URLs laden. Wenn Bilder in Kommentaren nicht wirklich nötig sind, ist das Abschalten die einfachste sichere Wahl.
Wie unterstütze ich Embeds (Videos, Tweets) am sichersten?
Nehmen Sie nicht beliebiges iframe-HTML von Nutzern an. Eine sichere Alternative: Nutzer fügen eine normale URL ein, Ihr Server prüft sie gegen eine Allowlist und erzeugt dann das Embed-HTML aus einer sauberen Vorlage nur für erlaubte Anbieter.
Welchen Fehler machen Teams oft bei der „Sanitierung“ von Rich-Text?
Sanitieren Sie serverseitig, nicht nur im Browser. Client-seitiges Filtern lässt sich leicht umgehen, indem direkt die API aufgerufen wird – dann wird unsicherer Inhalt gespeichert und später z. B. in Admin-Views oder E-Mails ausgeführt.
Wie kann ich schnell testen, ob mein Markdown-Rendering für XSS verwundbar ist?
Testen Sie mit einer kleinen Menge realistischer Payloads überall dort, wo Inhalt erscheint: öffentliche Seite, Admin-/Moderationsbildschirme, Benachrichtigungen und Vorschauen. Das Ziel: Die Eingabe bleibt überall inert – keine Popups, Redirects, unerwarteten UI-Änderungen oder verdeckten Netzwerkanfragen.