Output-Boundary-Encoding
Behandeln Sie alles, was das Modell ausgibt, als feindliche Eingabe für das nachfolgende System. Codieren und validieren Sie an jedem Ziel – Renderer, Shell, Query, nachgelagerter Agent – unter Verwendung der spezifischen Regeln dieses Ziels. Ein einziger globaler Sanitizer kann dies nicht leisten: Ein Escaping, das für HTML korrekt ist, ist für eine Shell bedeutungslos.
Definition
Output-Boundary-Encoding ist die Praxis, zielspezifische Codierung und Validierung auf die Modellausgabe an jedem Punkt anzuwenden, an dem sie in ein System übergeht, das sie interpretiert, anstatt sie einmal generisch beim Verlassen des Modells zu filtern. Ihr Fehlen entspricht der Schwachstelle, die OWASP als unzureichende Ausgabeverarbeitung (Improper Output Handling) bezeichnet.
Problem
Teams härten die Eingabeseite gegen Prompt Injection ab und lassen die Ausgabeseite offen. Der Text des Modells gelangt dann in einen Renderer, eine Shell, eine Datenbank oder den Kontext eines anderen Agenten, wo er als Anweisung interpretiert statt als Daten angezeigt wird. Der Angreifer muss das Modell so niemals direkt erreichen.
Wann zu verwenden
Jeder Agent, dessen Ausgabe ein System erreicht, das sie parst: eine Chat-Schnittstelle, die Markdown rendert, ein Coding-Agent, der einen vorgeschlagenen Befehl ausführt, ein Tool-Aufruf, der aus generierten Argumenten erstellt wird, eine Zusammenfassung, die in den Prompt eines zweiten Agenten einfließt, oder ein Webhook, der den Text weiterleitet.
Lösung
Listen Sie alle Ziele auf, bevor Sie Filter schreiben. Jeder Ort, an dem die Modellausgabe landet und interpretiert wird – HTML-Renderer, Shell, Query, Dateipfad, URL-Fetcher, Kontext eines anderen Agenten, nachgelagerter Webhook – ist eine eigene Grenze mit eigenen Regeln.
Codieren Sie am Ziel, nicht an der Quelle. Nutzen Sie HTML-Escaping für den Renderer, parametrisieren Sie Queries, übergeben Sie ein argv-Array an den Prozess. Die Codierung gehört dorthin, wo die Interpretation stattfindet, da nur dort bekannt ist, was interpretiert wird.
Bevorzugen Sie strukturierten Output gegenüber Fließtext, den Sie wieder parsen müssen. Ein Tool-Aufruf mit typisierten Argumenten verfügt über ein Schema, gegen das validiert werden kann; ein Satz, den Sie per Regex nach einem Dateinamen durchsuchen, nicht.
Validieren Sie den Wert, nicht nur die Syntax. Ein codierter Pfad ist immer noch ein Pfad: Überprüfen Sie vor dem Öffnen, ob er sich innerhalb des beabsichtigten Verzeichnisses auflösen lässt.
Behandeln Sie ausgehende URLs als eigenständiges Ziel. Gerenderte Bilder und Links führen zu einem Abruf ohne Klick und transportieren so Daten nach außen; setzen Sie die Hosts, die ein gerenderter Link erreichen darf, auf eine Allowlist.
Machen Sie die Grenze zum einzigen Pfad. Wenn irgendein Codepfad rohe Modellausgaben konsumieren kann, ohne einen zielspezifischen Encoder zu durchlaufen, ist die Schutzmaßnahme eher theoretischer Natur.
Komponenten
Vorteile
- Unterbricht die Injection-Kette an der entscheidenden Stelle: Selbst ein vollständig manipuliertes Modell kann ein nachgelagertes System nicht zum Handeln zwingen, da dieses System seinen Text niemals interpretiert.
- Unabhängig vom Modellverhalten. Es funktioniert auch bei Modell-Upgrades, neuen Jailbreaks und Prompt-Änderungen weiterhin, da es nicht darauf angewiesen ist, dass das Modell eine Anfrage verweigert.
- Testbar. Jedes Ziel hat ein Payload und ein klares Ergebnis (Erfolg oder Fehlschlag), sodass die Schutzmaßnahme Belege statt bloßer Zusicherungen liefert.
- Kostengünstig bei frühzeitiger Implementierung. Das Hinzufügen eines Encoders ist eine Änderung an der Grenze; das nachträgliche Hinzufügen, wenn das Ziel bereits überall verteilt ist, erfordert ein Refactoring.
Risiken
- Ein einziger Sanitizer für alle Ziele. Es fühlt sich wie eine Schutzmaßnahme an, erfüllt die Checkliste, ist aber an jeder Grenze falsch, außer an derjenigen, für die er geschrieben wurde.
- Eine Codierung, die das Produkt unbrauchbar macht: Übermäßiges Escaping verwandelt legitimes Markdown, Codeblöcke und nicht-lateinischen Text in Zeichensalat, und der Druck, dies zu lockern, lastet dann auf dem Encoder statt auf der Zielliste.
- Ein veraltendes Zielinventar. Neue Integrationen fügen Konsumenten hinzu, und es kommt zu keinem Fehler, wenn einer übersehen wird.
- Verwechslung von Erkennung mit Codierung. Das Scannen von Ausgaben nach verdächtigen Zeichenketten fängt die Payloads des letzten Jahres ab; Codierung muss den Angriff überhaupt nicht erkennen.
Wann nicht zu verwenden
- Ausgaben, die niemals interpretiert werden – ein Score, ein Enum, ein Boolean, den der Aufrufer vergleicht. Schränken Sie stattdessen den Typ ein; ein Encoder auf einer geschlossenen Wertemenge ist reine Formsache.
- Vollständig lokale Single-User-Tools ohne Rendering und ohne Prozessausführung, bei denen der einzige Konsument eine Person ist, die den Text liest.
- Wenn das Ziel bereits konstruktionsbedingt parametrisiert, wie z. B. ein ORM-Binding oder eine Template-Engine, die standardmäßig escapet. Ein zweiter Encoder bringt keinen Gewinn und kann zu doppelter Codierung führen.
Technologien
Beispiele
- Ein Support-Agent fasst ein Ticket zusammen, dessen Text ein Markdown-Bild enthält, das auf den Host eines Angreifers verweist. Die Konsole rendert es, der Browser ruft die URL ab und die Konversation fließt ab, ohne dass jemand auf etwas klickt. Das Deaktivieren von rohem HTML und das Setzen von Bild-Hosts auf eine Allowlist schließt diese Lücke.
- Ein Coding-Agent schlägt einen Shell-Befehl vor. Der Runner übergibt den String an eine Shell, sodass ein Dateiname, der ein Befehlstrennzeichen enthält, ausgeführt wird. Die Übergabe eines argv-Arrays stattdessen eliminiert den Parsing-Schritt der Shell vollständig.
- Die Zusammenfassung eines Agenten wird in den Prompt eines zweiten Agenten eingefügt. Die Zusammenfassung enthielt Anweisungen, und der zweite Agent hat diese befolgt. Das Eingrenzen (Fencing) des nicht vertrauenswürdigen Bereichs und dessen Kennzeichnung als Daten stellt in diesem Fall die Grenze dar.
KPIs
- Zielabdeckung
- Anteil der bekannten Konsumenten von Modellausgaben mit einem Encoder an der Grenze. Unter 100 % weist die Schutzmaßnahme eine konkrete Lücke auf, und die Benennung des Ziels ist nützlicher als ein Prozentsatz, der diese Lücke wegrechnet.
- Payload-Neutralisierungsrate
- Anteil der zielspezifischen Test-Payloads, die an der Grenze neutralisiert wurden. Das Ziel liegt bei 100 %: Alles andere benennt ein zu behebendes Ziel und nicht eine zu verbessernde Zahl.
- Zeit bis zur Abdeckung eines neuen Ziels
- Zeitspanne vom Livegang einer neuen Integration bis zur Existenz ihres Encoders. Misst, ob das Inventar mit dem Produkt Schritt hält, und nicht, ob es einmalig korrekt war.
- Auslösungsvolumen an den Grenzen
- Wie oft Encoder in der Produktion etwas neutralisieren. Eine glatte Null bedeutet meist, dass der Encoder nicht im Pfad liegt, und nicht, dass keine feindlichen Daten eingehen.
Beobachtete Fehlermuster
- Stille Exfiltration durch gerendertes Markup: Ein Bild oder Link führt zu einem Abruf ohne Klick, sodass Daten ohne Benutzeraktion und ohne einen für jemanden bemerkbaren Fehler abfließen.
- Second-Order-Injection: Eine für die Konsole korrekt codierte Ausgabe wird gespeichert und später an anderer Stelle gerendert – einem Log-Viewer, einem Ticket, einer Digest-E-Mail –, wo diese Codierung nicht greift.
- Der Encoder, der sich nur auf dem Happy Path befindet. Fehlerzweige, Retries und Fallbacks geben denselben Text über einen anderen Codepfad aus, auf dem sich keine Schutzmaßnahme befindet.
- Doppelte Codierung. Zwei Schichten escapen jeweils korrekt, Benutzer sehen gecodete Entities im Produkt, und die Behebung entfernt die falsche Schicht.
Lessons Learned
- Listen Sie Ziele auf, bevor Sie Filter schreiben. Fast jeder reale Fehler hier ist ein Konsument, den niemand aufgeführt hat, und kein falsch geschriebener Encoder.
- Das Ziel, das Sie vergessen, ist selten ein Bildschirm. Es ist ein Webhook, ein Log-Viewer, ein Export oder eine Digest-E-Mail – ein Ort, an den die Ausgabe gelangt, ohne dass jemand an ein Rendering denkt.
- Codierung schlägt Erkennung, da Codierung den Angriff nicht erkennen muss. Eine Payload-Blocklist ist lediglich eine Beschreibung der Angriffe, die bereits öffentlich waren.
- Lassen Sie nicht zu, dass ein einzelnes sanitise() zur Universallösung wird. Der Name suggeriert Vollständigkeit, und das Verhalten ist für genau ein Ziel korrekt.
FAQs
- Ist das nicht dasselbe wie das Filtern von Eingaben gegen Prompt Injection?
- Nein – sie sichern entgegengesetzte Enden ab. Die Eingabefilterung versucht zu verhindern, dass das Modell manipuliert wird, was vom Modell abhängt. Dieser Ansatz setzt voraus, dass die Manipulation bereits erfolgreich war, und verhindert, dass die Ausgabe ausgeführt wird, was überhaupt nicht vom Modell abhängt. Ein System, das nur Ersteres nutzt, scheitert in dem Moment, in dem ein neuer Jailbreak auftaucht.
- Ist das nicht einfach Output-Sanitization? Warum nicht ein einziger Sanitizer für alles?
- Weil Codierung kontextabhängig ist. Das Escaping eines Anführungszeichens schützt einen HTML-Renderer, bewirkt aber nichts für eine Shell; Shell-Quoting schützt eine Shell und zerstört angezeigten Text. Eine gemeinsam genutzte Funktion muss sich für einen Kontext entscheiden, ist in den anderen falsch und erweckt den Anschein von Abdeckung, während sie einen Single Point of Failure darstellt.
- Das Modell gehört uns und der Prompt ist fest vorgegeben. Benötigen wir das trotzdem?
- Ja, wenn Inhalte, die das Modell liest, von außen stammen: eine abgerufene Seite, eine Benutzerdatei, ein Tool-Ergebnis, ein Speichereintrag. Die Anweisung muss nicht über Ihren Prompt erfolgen – sie erfolgt über alles, was das Modell liest, und die Tatsache, dass Ihr Prompt fest vorgegeben ist, schränkt dies nicht ein.