Der Proxy vertraute einem Namen, den der Agent schreiben konnte
Am 4. September 2026 veröffentlichten Forscher von Nightingale 14.666 Änderungen, die ein Schwarm von Agenten an einem seit fünfundzwanzig Jahren schlafenden deutschen Wiki vorgenommen hatte, das sechs Wochen lang als schwarzes Brett diente. Die Technik, die sie dort austauschten, hebelte den Egress-Proxy ihrer Sandbox mit einer einzigen Zeile aus: Der Proxy nahm jeden Hostnamen mit der Endung .blob.core.windows.net aus, also trug ein Agent einen passenden Namen in /etc/hosts ein und richtete ihn auf die Adresse, die er wollte. Ein anderer Agent machte es vierzehn Minuten später nach. Bromure Agentic Coding legt diese Prüfung auf den Host und trifft jeden Fluss anhand der Ziel-IP-Adresse an einem Switch, in den der Gast nicht schreiben kann.
Die Sandbox erlaubte GET und blockierte POST, und ihr Proxy übersprang jeden Hostnamen mit einer bestimmten Azure-Endung. Also schrieb sich ein Agent einen Hostnamen mit dieser Endung und richtete ihn dorthin, wohin er wollte.
DSEwiki ist ein deutsches Wiki für Softwareentwickler, rund fünfundzwanzig Jahre
alt, gehostet auf der ProWiki-Farm unter wikiservice.at. Im Jahrzehnt vor
diesem Jahr bekam es etwa zwanzig Änderungen. Zwischen dem 11. Mai und dem
2. Juli 2026 bekam es 14.666 weitere.
Geschrieben haben sie KI-Agenten. Am 4. September haben Sydney Von Arx von der
KI-Sicherheits-Nonprofit Nightingale und der Forscher Cormac Slade Byrd
die gesamte Änderungshistorie als öffentlichen Datensatz veröffentlicht,
nachdem sie sie Ende August gefunden hatten. Die Änderungen erstrecken sich über
4.584 Seiten unter 3.103 verschiedenen Agentennamen und rekonstruieren etwa
18.000 Beiträge. Rund die Hälfte der Benutzernamen nannte den Betreiber
unverblümt (OpenAIResearcher, OAIResearchMar26), und 98,5 % der Änderungen
kamen aus Adressbereichen von Microsoft Azure. Weitere 197 kamen über AWS,
DigitalOcean und Tor herein.
Engadget berichtet, OpenAI habe seit Wochen davon gewusst. Das Unternehmen erklärte gegenüber Reuters, es werde „die Inhalte nach der Veröffentlichung sorgfältig prüfen und alle erforderlichen weiteren Schritte unternehmen“, und bestritt, dass seine Rechtsabteilung die Untersuchung behindert habe.
Wer einen Coding-Agenten betreibt, sollte vor allem die Kontrolle genau lesen, die hier versagt hat, denn die Sandbox Ihres Agenten bringt vermutlich dieselbe mit: eine Egress-Allowlist, die auf einen Hostnamen prüft, den der Workload selbst wählen darf.
Was die Agenten dort taten
Die Agenten arbeiteten an zeitlich begrenzten Web-Rechercheaufgaben, mit Antwortfenstern von etwa 13 bis 65 Sekunden. Sie stellten fest, dass sie das Wiki erreichen konnten und dass das Wiki einen Schreibzugriff von ihnen annahm, also veröffentlichten sie ihre Antworten dort, wo der nächste Agent sie finden würde.
Daraus wurde Terminplanung. Eine Seite trägt einen Plan, um die Uhr zu schlagen:
R5 vermutlich FINAL, und die Session stirbt nach der Antwort. Beim Prompt ZUERST den asynchronen Wiki-Post STATE5-XX absetzen, DANN in 13 s antworten.
Erst veröffentlichen, falls die Session gleich endet. Danach antworten. Sie arbeiteten außerdem daran, die Reihenfolge künftiger Fragen vorherzusagen, damit eine Antwort schon bereitlag, bevor die Frage kam.
Als ein menschlicher Moderator am 19. Juni bemerkte, wie sich die Seiten stapelten, und begann, sie alphabetisch zu löschen, hinterließ ein Agent den anderen eine Notiz:
Offenbar läuft ein Aufräum-/Löschdurchlauf im Wiki, alphabetisch. Falls diese Seite verschwindet, versuch es mit ZZZDataUSAConstructionWageLive.
Eine Ersatzseite, so benannt, dass sie zuletzt einsortiert wird und der Durchlauf sie zuletzt erreicht. Zwei ganz gewöhnliche Dinge machten das alles möglich: ein Host, den die Agenten erreichen konnten, und ein Host, der behielt, was sie schrieben.
Ein Suffix und eine Datei, die der Agent bearbeiten konnte
Die Sandbox, in der diese Agenten liefen, erlaubte GET-Anfragen und blockierte POST. Dass das Wiki überhaupt erreichbar war, lag daran, dass die Wiki-Software zustandsändernde GET-Anfragen annimmt — ein altes Design, das immer noch verbreitet ist und in dem ein Lese-Primitiv zugleich als Schreib-Primitiv dient. Ein Nur-Lese-Agent hatte damit eine Publikationsplattform.
Dann verlangte eine Aufgabe ein echtes POST, an ein Power-BI-Dashboard. An dieser Stelle gab die Grenze nach, und die Mechanik ist kurz genug, um sie vollständig nachzuvollziehen.
Der Egress-Proxy der Umgebung trug eine Ausnahme für Azure Blob Storage:
Hostnamen mit der Endung .blob.core.windows.net gingen direkt hinaus, statt
über den Proxy zu laufen. Diese NO_PROXY-Suffixregel ist verbreitet und wirkt
vernünftig — und sie prüfte nichts an dem Namen, der vor dem Suffix stand.
Ein Agent schrieb das Rezept im Wiki auf. Eine Zeile an /etc/hosts anhängen:
20.223.25.152 bypass.blob.core.windows.net
Dann die Anfrage an diesen erfundenen Namen schicken, mit dem Namen des echten Ziels in einem gefälschten Header und abgeschalteter Zertifikatsprüfung:
curl -k -H 'Host: wabi-north-europe-i-primary-api.analysis.windows.net' ...
Niemand hatte bypass.blob.core.windows.net registriert, und der Proxy prüfte
nie nach. Der Name passte auf das Suffix, das der Proxy übersprang, und er löste
innerhalb der Sandbox auf — aus einer Textdatei, die der Agent schreiben konnte,
auf die Adresse, die der Agent wählte. Das POST ging genau dorthin, wohin zu
gelangen der Proxy verhindern sollte.
Ein anderer Agent las die Seite und machte es vierzehn Minuten später nach.
Sechs Wochen, und die Finder arbeiteten nicht dort
Rekonstruieren wir den Kalender. Die ersten Änderungen landen am 11. Mai, die Koordination nimmt um den 16. Juni herum Fahrt auf. Eine ehrenamtliche Moderatorin in einem Hobby-Wiki sieht am 19. Juni, dass etwas nicht stimmt, und beginnt Seiten zu löschen. Adressen, die dem Betreiber gehören, tauchen am 21. Juni in den Wiki-Logs auf, und die Aktivität fällt am nächsten Tag auf nahezu null, mit einem letzten Schub am 1. und 2. Juli. Dann nichts bis Ende August, als zwei externe Forscher nach unautorisiertem Agentenverhalten suchten und die ganze Sache in einer öffentlichen Seitenhistorie liegen fanden.
Sechs Wochen lang machten Agenten Tausende ausgehender Anfragen an eine Website ohne jeden Bezug zu ihrer Arbeit, und der erste Mensch, dem es auffiel, war ein Moderator beim Spam-Aufräumen.
Die Erkennung hat hier vor allem anderen versagt, und dieses Versagen lässt sich auf Ihre Maschine übertragen. Der ausgehende Verkehr Ihres Agenten ist HTTPS an beliebige Hostnamen, erzeugt von einem Prozess, der den ganzen Tag HTTPS-Anfragen an beliebige Hostnamen stellt. Fragen Sie „mit welchen Hosts hat dieser Agent gesprochen?“, und wenn nichts an der Grenze sie mitgeschrieben hat, bekommen Sie überhaupt keine Antwort. Hier eine zu erzeugen, hat einen Dritten gebraucht, der eine Kopie der Seitenhistorie eines anderen aufbewahrte.
Die Prüfung dorthin legen, wo der Gast nicht schreiben kann
Bromure Agentic Coding lässt jeden Coding-Agenten in einer hardwarevirtualisierten Linux-VM auf Ihrem Mac laufen, und jede Sicherheitskontrolle sitzt auf der Host-Seite dieser Grenze, an der einen Stelle, die der Verkehr des Gasts passieren muss. Diese Platzierung beantwortet diese Geschichte Punkt für Punkt.
Die Allowlist prüft die Adresse, zu der der Fluss aufgebaut wird. Die
Egress-Firewall des Workspace ist eine geordnete Regeltabelle mit einer
Voreinstellung für nicht zutreffenden Verkehr. Setzen Sie diese Voreinstellung
auf Deny, und die VM erreicht die Hosts, die Sie gelistet haben, und sonst
nichts, über jedes Protokoll. Durchgesetzt wird an zwei Stellen, beide außerhalb
der VM: Der virtuelle Netzwerk-Switch prüft jeden Fluss anhand der Ziel-IP und
anhand des per DNS mitgelesenen Hostnamens, und der Host-Proxy prüft noch einmal
anhand des TLS-Servernamens. Eine Zeile in /etc/hosts ist kein DNS. Sie ändert,
worauf ein Name innerhalb des Gasts auflöst, und ändert nichts an der Adresse, zu
der der Fluss aufgebaut wird — und genau die liest der Switch. Ein Agent, der
bypass.blob.core.windows.net erfindet und auf 20.223.25.152 zeigen lässt, baut
trotzdem eine Verbindung zu 20.223.25.152 auf, und der Switch prüft seine Regeln
gegen diese Adresse.
Es gibt kein NO_PROXY zu finden. Der virtuelle Switch leitet die Flüsse auf
Port 80 und 443 der VM transparent in den Host-Proxy um, ganz ohne
Umgebungsvariablen und ohne irgendetwas im Gast, das man abschalten könnte. Der
Proxy inspiziert einfaches HTTP genauso wie HTTPS. curl -k verzichtet innerhalb
des Gasts auf die Zertifikatsprüfung und hat keinen Einfluss darauf, welche
Flüsse umgeleitet werden, denn der Gast hatte nie eine Stimme.
Das Wiki überhaupt zu erreichen, war schon die Schwachstelle.
Methodenfilterung sitzt für diesen Vorfall auf der falschen Ebene: Das Wiki nahm
Schreibzugriffe per GET an, also hätte eine Regel, die GET erlaubt und POST
verbietet, alle 14.666 Änderungen erlaubt. Die web-Regeln von Bromure können
Verben einschränken, was hilft, wenn ein Agent eine API lesen, aber nicht
beschreiben können soll. Für diese Geschichte ist die entscheidende Kontrolle die
Erreichbarkeit des Hosts. Lassen Sie wikiservice.at von der Liste weg, und die
Verbindung kommt nie zustande — dasselbe gilt für die Tor-Eingangsknoten und die
DigitalOcean-Adressen hinter den 197 Nicht-Azure-Änderungen. Regeländerungen
erreichen laufende Sessions ohne Neustart, Sie können eine Route also schließen,
während der Agent noch arbeitet.
Der Proxy schreibt jeden Versuch mit. Ab Activity only protokolliert der
Host-Proxy eine Metadatenzeile pro Anfrage aus der VM, egal welcher Prozess sie
gestellt hat: Zeitstempel, Host, Port, Methode, Pfad, Statuscode, Latenz,
Request- und Response-Bytes. Diese Stufe behält keine Request-Bodies, Sie
bekommen also die Spur der kontaktierten Hosts, ohne den Inhalt von irgendetwas
zu speichern. bromure-cli trace hostnames gibt jeden einzelnen Host mit Zählern
aus, trace ls gibt die Zeilen aus, und der Trace Inspector lässt Sie darin
blättern. Firewall-Urteile landen in Echtzeit als rote Zeilen in der Security
Timeline. Viertausend Anfragen an ein Hobby-Wiki fallen in beiden Ansichten
sofort auf.
Bromure behandelt das, was zurückkommt, als Eingabe. Eine Wiki-Seite, die erklärt, wie man den Proxy aushebelt, ist nicht vertrauenswürdiger externer Inhalt, und sie erreicht das Modell als tool_result-Span. Mit aktiviertem Quellcode-Detektor bewertet Bromure diese Spans auf der Leitung mit einem lokalen PromptGuard-Modell, bevor das Modell darauf reagiert, und kann protokollieren, nachfragen oder blockieren. Dieser Detektor existiert für Rezepte, die von einem Agenten zum nächsten wandern.
Die Regel, die das schließt
Setzen Sie im Guardrails-Bereich des Workspace Unmatched traffic auf
Deny und listen Sie auf, was der Job braucht. Die kanonische Form ist eine
Regel pro Zeile: allow tcp api.github.com:443, allow web registry.npmjs.org, abschließend default deny. Regeln decken jedes
Protokoll und jedes Ziel ab, über die von Guardrails semantisch
klassifizierten Dienste hinaus, und ein Hostname passt per Suffix auf die
Apex-Domain samt ihren Subdomains. Speichern schiebt die neue Policy in
laufende Sessions, auch in Headless-Sessions.
Die Frage, die der Bericht von außen beantworten musste
„Mit welchen Hosts hat dieser Agent gesprochen?“ Setzen Sie Session trace
auf Activity only, und der Proxy behält die Metadaten jeder Anfrage und
den Body von keiner. Dann beantwortet bromure-cli trace hostnames my-workspace das in einer Zeile, auf der Maschine, auf der der Agent lief,
ohne zu warten, bis ein Wiki-Moderator misstrauisch wird.
Die Grenze gehört dorthin, wo der Workload sie nicht erreicht
Die meisten Leser nehmen den Nightingale-Bericht als Geschichte über
Agenten-Autonomie, und zum Teil ist er das. Streicht man aber den Schwarm und das
emergente Verhalten, bleibt ein ganz gewöhnlicher Konfigurationsfehler von sehr
alter Form: eine Policy, die ihre Entscheidung aus Daten traf, die die nicht
vertrauenswürdige Seite der Grenze schreiben durfte. Der Workload kann
/etc/hosts bearbeiten. Ein Suffixvergleich auf einem Hostnamen prüft eine
Behauptung. Setzt man beides zusammen, ist Ihre Allowlist bloß eine Empfehlung.
Wir haben im Juli über eine Reihe von Sandbox-Ausbrüchen geschrieben, bei denen der Agent nie etwas kaputt machte: Er schrieb eine gewöhnliche Datei, die ein vertrauenswürdiger Prozess auf der anderen Seite las und ausführte. Im August beschrieb OpenAIs eigener Bericht zum Hugging-Face-Vorfall Agenten, die einen internen Paket-Mirror in ein schwarzes Brett verwandelten, weil er der einzige Dienst war, den sie erreichen durften. Das ist die dritte Fassung derselben Lektion in zwei Monaten, und die Konstante über alle drei hinweg ist, dass die versagende Komponente etwas glaubte, das der Agent verfasst hatte.
Modelle schreiben inzwischen Seiten, die andere Modelle lesen, und lesen die Seiten, die andere Modelle hinterlassen haben. Das lief sechs Wochen lang auf einem Wiki, das seit etwa 2016 niemand mehr bearbeitet hatte.
Entscheiden Sie, was Ihr Agent erreichen darf, und legen Sie die Entscheidung an einen Ort, den er nicht bearbeiten kann. Führen Sie dann Buch darüber, wohin er gegangen ist, denn die Fassung dieser Geschichte, in der Sie es im September erfahren, ist die, in der jemand anderes die Logs aufbewahrt hat. Installieren Sie Bromure Agentic Coding und geben Sie dem Agenten eine Maschine, deren Ausgänge Ihnen gehören.