Zurück zu allen Beiträgen
Veröffentlicht am · von Renaud Deraison

Die Webseite namens localhost

Am 17. August nahm die CISA Rays CVE-2025-62593 in ihren Katalog bekannter ausgenutzter Schwachstellen auf. Es ist Remote Code Execution auf dem eigenen Rechner des Entwicklers, ausgeliefert von einer Webseite, die er besucht hat, und sie erreicht einen Dienst, der immer nur auf 127.0.0.1 lauschte. Coding-Agenten füllen dieses Interface das ganze Jahr über mit unauthentifizierten Servern. Bromure Agentic Coding legt sie dorthin, wo kein Browser-Tab hinwählen kann.

Ihr Dev-Server, Ihr Notebook und Ihr lokales Dashboard binden jeweils einen unauthentifizierten Port an 127.0.0.1, mit der Begründung, nur die Person an der Tastatur könne ihn erreichen. Eine Webseite kann es ebenfalls. Die Browser-Policy, die im Weg steht, fällt in etwa sechzig Sekunden auseinander.

Am 17. August nahm die CISA eine Schwachstelle in ihren Katalog bekannter ausgenutzter Schwachstellen auf und gab Bundesbehörden bis zum 20. August Zeit, sich darum zu kümmern. The Hacker News schrieb am nächsten Morgen darüber. Der Eintrag ist CVE-2025-62593, eine Code-Injection-Lücke in Ray, dem Framework für verteiltes Rechnen, mit dem ein großer Teil der Branche Modelle trainiert und ausliefert.

Der Code läuft auf dem eigenen Laptop eines Entwicklers. Jemand hatte Ray für seine Arbeit lokal laufen, öffnete eine Webseite, und die Seite führte einen Befehl für ihn aus.

Drei gewöhnliche Tatsachen, schlecht angeordnet

Das Advisory bewertet die Lücke mit 9,4 und beschreibt eine Kette ohne einen einzigen exotischen Schritt.

Rays Jobs-API nimmt einen Shell-Befehl entgegen. Das ist das Produkt: Sie senden ein POST an /api/jobs/ mit einem Entrypoint, und der Cluster führt den Befehl aus. Das Dashboard lauscht auf Port 8265, und weder es noch die Job-Endpunkte verlangen eine Authentifizierung. Das war eine bewusste Entscheidung der Maintainer, deren Position lautet, dass Sicherheit und Isolation außerhalb des Ray-Clusters durchgesetzt werden müssen. Man stellt es irgendwohin, wo nur vertrauenswürdige Aufrufer hinkommen, und das Loopback-Interface eines Laptops klingt nach so einem Ort.

Ray hatte durchaus einen Schutz gegen Browser. Es prüfte, ob der User-Agent-Header mit Mozilla beginnt, und wies solche Anfragen ab, in der Annahme, ein Browser könne nicht über seinen eigenen User-Agent lügen. In Firefox und Safari erlaubt die Fetch-API einer Seite, diesen Header auf einen beliebigen Wert zu setzen.

Bleibt die Same-Origin-Policy, die eine Kontrolle zwischen einer Seite im Internet und einem Dienst auf Ihrem Rechner. DNS-Rebinding nimmt sie auseinander. Der Angreifer liefert die Seite von einer Domain aus, deren DNS-Einträge er kontrolliert, mit sehr kurzer Time-to-live. Die Seite lädt und löst dann dieselbe Domain erneut auf 127.0.0.1 auf. Der Browser behandelt sie weiterhin als denselben Origin, gleicher Hostname und gleicher Port, während jede Anfrage nun an Ihren Rechner geht. Der veröffentlichte Proof of Concept benutzt singularity, ein Rebinding-Framework, das seit Jahren öffentlich ist.

Verketten Sie das, und eine bösartige Seite oder eine Malvertisement-Anzeige auf einer Seite, der Sie vertraut haben, postet einen Job mit einem Shell-Befehl darin an Ihre Ray-Instanz. Chrome ist durch einen unabhängigen Bug geschützt; Firefox und Safari sind es nicht. Avi Lumelsky bei Oligo stellte die Theorie zum User-Agent-Bypass auf; Jonathan Leitschuh, damals bei Socket, baute die Rebinding-Kette und die Offenlegung. Ray 2.52.0 behebt das und ergänzt eine optionale Token-Authentifizierung, standardmäßig aus.

Wie eine Seite zum Client für Ihren Laptop wird1 · Sie laden die Seiteevil.example → 203.0.113.7TTL: 1 Sekunde2 · der Eintrag ändert sichevil.example → 127.0.0.1gleicher Origin, neues Ziel3 · Schutz = ein Headerfetch(url, headers: UA)Firefox und Safari erlauben es4 · POST /api/jobs/127.0.0.1:8265entrypoint = shellWORAUF SICH JEDE SCHICHT VERLIESSRay„das Netz um uns herum ist sicher“die User-Agent-Prüfung„ein Browser kann darüber nicht lügen“Same-Origin-Policy„ein Hostname heißt eine Adresse“Nur die dritte ist eine Sicherheitskontrolle, und Rebinding ist älter als die meisten Werkzeuge, die sich darauf stützen.
Die Rebinding-Kette. Jeder Schritt ist dokumentiertes Verhalten eines gut gepflegten Werkzeugs: eine kurze DNS-TTL, ein Fetch-Header, den die Spezifikation einer Seite zu setzen erlaubt, und ein API-Endpunkt, dessen ganzer Zweck das Ausführen von Befehlen ist.

Die Angreifer waren vor dem Advisory da. Das RondoDox-Botnet griff die Lücke zwei Tage vor der öffentlichen Offenlegung auf, und Oligos Recherche ShadowRay 2.0 verfolgt eine Kampagne, die Ray-Deployments in ein sich selbst verbreitendes Botnet verwandelt: kompromittierte Cluster scannen nach weiteren Ray-Instanzen und infizieren sie, ein Cronjob holt alle fünfzehn Minuten frische Payloads aus angreiferkontrollierten Repositories, und die Payload schürft Monero, öffnet Reverse Shells und nimmt mit, was sie findet. Oligo zählte mehr als 230.000 exponierte Ray-Server, eine Verzehnfachung seit dem ersten Bericht 2024. Ein einziger kompromittierter Cluster gab 240 GB Quellcode, Modelle und Datensätze preis.

Was auf Ihrem Rechner lauscht

Lassen Sie Ray beiseite und zählen Sie etwas anderes: die unauthentifizierten HTTP-Server, die gerade jetzt an Ihr Loopback-Interface gebunden sind, und wie viele davon Sie ohne Nachsehen benennen könnten.

Führen Sie nach einer Arbeitswoche lsof -iTCP -sTCP:LISTEN -P aus, und die Liste wird länger, als Sie schätzen würden. Vite auf 5173. Ein FastAPI-Dienst unter uvicorn --reload auf 8000. Jupyter auf 8888, mlflow ui auf 5000, der veröffentlichte Port eines Postgres-Containers, ein MCP-Server auf 3000, ein Debug-Port, den ein abgestürzter Testlauf offen gelassen hat. Keiner davon fragt, wer Sie sind. Ihre Autoren machten dieselbe Annahme wie Rays Maintainer, und sie hält, bis ein Tab in einem anderen Fenster anfängt, Anfragen zu stellen.

Agenten haben das Volumen verändert. Ein Agent, der an einem Ticket arbeitet, startet Dienste ganz selbstverständlich. Er startet den Dev-Server, um seine eigene Änderung zu prüfen, fährt eine Datenbank hoch, um die Migration auszuführen, startet das Notebook, um sich die Daten anzusehen, startet die API, um einen Endpunkt aufzurufen. Er tut das mehrmals pro Nachmittag, über mehrere Workspaces hinweg, und er räumt nicht auf, weil ihm das niemand sagt. Die Prozesse überleben die Aufgabe. Am Donnerstag trägt das Interface ein Dutzend Dienste, die Sie nicht selbst gestartet haben und aus dem Gedächtnis nicht aufzählen könnten, jeder ohne Authentifizierung gebunden, weil der Quickstart des Frameworks sagt, auf localhost sei alles in Ordnung.

Rays Position liest sich anders auf einem Rechner, auf dem ein Coding-Agent läuft: Sicherheit und Isolation müssen außerhalb des Dings durchgesetzt werden, das Sie gestartet haben. Auf einem Laptop, auf dem sich Agent und Browser einen Kernel teilen, hat „außerhalb“ keinen Platz zum Sitzen.

In einem Bromure-Workspace liegt 8265 nicht auf Ihrem Mac

Bromure Agentic Coding betreibt jeden Workspace in einer eigenen Ubuntu-VM auf Apples Virtualization-Framework. Das ist die ganze Antwort auf diesen Angriff, und sie hält, ohne dass irgendjemand irgendetwas patcht.

Wenn der Agent ray start --head ausführt, bindet sich das Dashboard innerhalb der VM an 127.0.0.1:8265. Das Loopback-Interface Ihres Macs ist ein anderes Interface. Ein umgebundenes fetch() aus Safari auf dem Host löst evil.example auf 127.0.0.1 auf, verbindet sich mit dem macOS-Loopback und bekommt nichts, weil der Dienst, nach dem die Seite gesucht hat, einen Kernel weiter liegt. Die veröffentlichte Kette zielt auf 127.0.0.1, die Adresse, auf die singularity umbindet und die das Advisory nennt, und in einem Bromure-Workspace ist auf dieser Adresse nichts.

Dasselbe gilt für die zweite Hälfte des Advisories, den Teil über den Browser als Vermittler, um Ray-Instanzen innerhalb eines Firmennetzes zu erreichen, die niemand ins Internet gestellt hat. Workspaces laufen standardmäßig im NAT-Modus, und das Handbuch ist präzise darin, was das bringt: die VMs sind von Ihrem Mac aus erreichbar, aber nicht in Ihrem physischen LAN exponiert, und eingehende Verbindungen von anderswo sind nicht möglich, sofern Sie nicht absichtlich einen Dienst veröffentlichen. Veröffentlichen heißt: ein Cloudflare-Quick-Tunnel pro Dienst, den Sie per Knopfdruck starten.

Und Sie bekommen das Inventar. Die Karte Lauschende Ports im Workspace-Dashboard fragt im Gast ss -tulnpH ab und listet jeden von außen erreichbaren Socket als das VM-IP:Port, zu dem Sie sich verbinden würden, samt Name des Prozesses, der ihn hält. Die Karte blendet reine Loopback-Sockets aus, da nichts außerhalb der VM sie erreichen kann. Dieselbe Liste kommt aus bromure-cli vm <id> -L. Diese Liste ist die Volkszählung der Hinterlassenschaften des Agenten, und macOS führt keine solche Liste für Sie.

KONVENTIONELL: ein Loopback, von allem geteiltIhr Mac · 127.0.0.1:8265 ray · :5173 vite · :8888 jupyter · :3000 mcp:8000 uvicorn · :5000 mlflow · :5432 postgresvom Agenten gestartet, überlebt die Aufgabe, nichts authentifiziertein Tab in einem anderen Fensterbindet um auf 127.0.0.1und erreicht alles davonBROMURE: das Loopback des Agenten ist nicht IhresWorkspace-VM · eigenes 127.0.0.1:8265 ray · :5173 vite · :8888 jupyterNAT: nicht in Ihrem physischen LANerreichbare Sockets im Dashboard gelistetIhr Mac · 127.0.0.1(nichts vom Agenten Gestartetes)die Adresse, die der Exploit wähltderselbe Tabverbindet sich, findetein leeres Interface
Derselbe Befehl, zwei Anordnungen. Konventionell landet alles, was der Agent startet, auf demselben Haufen, den eine Webseite adressieren kann. In Bromure liegen die Dienste des Agenten hinter einer Netzgrenze, und was erreichbar ist, ist eine Liste, die Sie lesen können.

Der Sprung nach dem ersten

ShadowRay 2.0 lohnt die Lektüre wegen dem, was ein kompromittierter Knoten als Nächstes tut, denn das ist der Teil, für den die Isolation geradestehen muss. Er scannt nach weiteren Ray-Instanzen und infiziert sie. Er installiert einen Cronjob, der alle fünfzehn Minuten neue Anweisungen holt. Er greift nach allen Zugangsdaten und Datensätzen, die auf dem Rechner liegen.

Jedes davon ist eine ausgehende Verbindung, und ein Bromure-Workspace gleicht ausgehende Verbindungen mit Regeln ab, die Sie geschrieben haben. Der Editor Ausgehende Verbindungen im Guardrails-Bereich enthält ein Regelwerk im pf-Stil: erlauben oder verweigern, nach Host, IP oder CIDR, Protokoll und Port, von oben nach unten ausgewertet, wobei die erste Übereinstimmung gewinnt, plus eine Einstellung für Verkehr, der auf nichts passt.

allow web  api.github.com:443
allow tcp  registry.npmjs.org:443
deny  any  10.0.0.0/8
deny  any  192.168.0.0/16
default deny

Zwei Schichten setzen dasselbe Regelwerk durch. Der virtuelle Switch bewertet jeden Flow nach Ziel-IP und nach den Hostnamen, die er aus den DNS-Antworten des Gasts mitgehört hat, sodass eine gegen einen Namen geschriebene Regel weiter greift, wenn sich die Adresse darunter bewegt. Der MITM-Proxy bewertet dieselben Regeln nach TLS-SNI und bei web-Regeln nach HTTP-Methode, sodass Sie allow web api.example.com GET,HEAD schreiben können. Bromure injiziert bei einer verweigerten TCP-Verbindung ein Reset, sodass der Connect fehlschlägt, statt zu hängen.

Diese ganze Durchsetzung läuft auf Ihrem Mac, außerhalb der VM. Transparente Interception ist standardmäßig an und leitet HTTP und HTTPS des Gasts zu Bromure um, selbst wenn drinnen etwas HTTP_PROXY und HTTPS_PROXY löscht. Ein Agent, der die falsche Webseite gelesen hat, oder eine Payload, die mit einem Paket mitgekommen ist, sitzt auf der falschen Seite der Regeln, die er ändern müsste. Bromure schreibt jede Entscheidung als Firewall-Zeile in Fenster → Sicherheits-Timeline: Host, Port, erlaubt oder blockiert, in einer einzigen chronologischen Tabelle neben den Entscheidungen zu Zugangsdaten, Lieferkette und Prompt-Injection.

Der Fünfzehn-Minuten-Cronjob hat dasselbe Problem in der anderen Richtung. Ein Workspace besteht aus drei Speicherschichten, und zwei davon können Sie wegwerfen: Home löschen… setzt /home/ubuntu auf den Zustand nach dem Klonen zurück, Auf Basis zurücksetzen… klont die System-Disk des Workspace erneut aus dem Basis-Image, und das Basis-Image bleibt zur Laufzeit schreibgeschützt. Eine Crontab im Home-Verzeichnis überlebt keines von beiden.

localhost war eine Konvention

Rays Maintainer waren nicht nachlässig. Sie schrieben ein Rechen-Framework, das Befehle ausführt, sagten das in der Doku und trugen Ihnen auf, eine Grenze darum zu ziehen. Die Leute, die es auf einem Laptop betreiben, hielten das Loopback-Interface für diese Grenze, was die Schlussfolgerung ist, zu der Dev-Server, Notebooks und lokale Dashboards seit zwanzig Jahren einladen. Das war eine Konvention und keine Kontrolle. Sie hielt, solange die einzigen Dinge auf Ihrem Rechner Dinge waren, die Sie selbst gestartet hatten, und sie hörte auf zu halten, als Browser eine Skript-Engine bekamen.

Ein Agent vergrößert die Lücke jeden Nachmittag, ein npm run dev nach dem anderen. Sorgfalt schließt sie nicht, denn Sorgfalt setzt voraus zu wissen, was lauscht, und die Liste ändert sich mit jedem Befehl, den der Agent ausführt.

Hören Sie auf, die beiden ein Interface teilen zu lassen. Stecken Sie die Arbeit des Agenten in eine eigene Maschine, in der die Ports, die er öffnet, Ihrem Mac antworten und sonst niemandem, in der die erreichbaren Sockets eine Liste sind, die Sie lesen, statt einer Annahme, die Sie geerbt haben, und in der die ausgehenden Verbindungen gegen Regeln geprüft werden, die der Workspace nicht ändern kann. Eine Seite, die auf 127.0.0.1 umbindet, findet dann ein leeres Interface und kassiert eine Abfuhr.


Quellen: CISA, „CISA Adds One Known Exploited Vulnerability to Catalog“ (17. August 2026) · The Hacker News, „CISA Flags Actively Exploited Ray Flaw That Can Trigger Browser-Based RCE“ (18. August 2026) · GitHub Advisory GHSA-q279-jhrf-cc6v (CVE-2025-62593) · Oligo Security, „ShadowRay 2.0“