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

Die Doku nannte ein Paket, das niemandem gehörte

Forscher haben 6.214 Firmendomains nach llms.txt durchsucht, jener maschinenlesbaren Datei, die Unternehmen heute für KI-Agenten veröffentlichen, und darin 237 genannte Pakete und Domains gefunden, die nie jemand registriert hatte. Ein paar davon haben sie selbst genommen. Der erste Coding-Agent in einem Fortune-500-Netz installierte eines davon in unter vier Minuten. Der Angreifer hat weder einen Maintainer noch eine Registry noch ein Repository angefasst. Die Altersschwelle von Bromure Agentic Coding ist ab Werk bei zwei Tagen aktiv, und ein Name, den ein Angreifer belegt, ist konstruktionsbedingt ein brandneuer Publish.

Ein Anbieter schrieb in seine eigene Dokumentation einen Installationsbefehl für ein Paket, das er nie veröffentlicht hat. Der Name lag dort, frei, für jeden zu haben. Coding-Agenten lasen die Doku, glaubten ihr und führten die Installation aus.

Irgendwann in den letzten zwei Jahren begannen Ihre Entwicklerwerkzeuge, eine neue Datei auszuliefern. Sie liegt neben robots.txt, sie heißt llms.txt, und sie enthält eine Zusammenfassung des Produkts in reinem Text, geschrieben für eine Maschine statt für einen Menschen. Was die API tut. Welche Endpunkte zählen. Welches Paket man installiert, um loszulegen. Coding-Agenten holen sie sich, und weil sie von der eigenen Domain des Anbieters kommt, behandeln sie sie als gesicherte Tatsache.

Ein Forscher namens Alon Hertz, der unter dem Namen PANDEX arbeitet, sah nach, was diese Dateien einem Agenten aufzutragen. Seine Methode braucht drei Schritte und keinen Exploit: llms.txt und llms-full.txt aus Firmenverzeichnissen ziehen, echte Agenten in Sandboxes darauf ansetzen und beobachten, wonach die Agenten greifen, dann jeden Paketnamen und jeden Hostnamen, der dabei herauskommt, gegen npm, PyPI und die Domain-Registries prüfen. Er beschreibt das Werkzeug auf whatwouldai.do, unter einem Slogan, der sich als der Befund entpuppte: Agenten handeln auf alles hin.

Der Scan umfasste 6.214 aktive Domains aus Fortune-500-Konzernen, Big Tech, Fintech und Rüstungsunternehmen sowie mehr als 8.000 dieser Dateien. In 120 davon existierte das, was die Datei dem Agenten zu installieren auftrug, gar nicht. Über den gesamten Korpus hinweg lagen 237 genannte Paketnamen und Hostnamen frei: verfügbar auf npm, PyPI, RubyGems, NuGet, crates.io und Packagist, oder frei als Subdomains bei Vercel, Render, Fly und Netlify. Jeder konnte sie zum Preis einer Anmeldung nehmen.

Also nahmen die Forscher eine Handvoll, veröffentlichten unter diesen Namen harmlose Pakete mit einem Beacon, das beim Installieren nach Hause funkt, und warteten.

Der erste Rückruf traf in unter vier Minuten ein. Der zweite kam binnen einer Stunde. Über den folgenden Zeitraum protokollierten sie Installationen aus Dutzenden Organisationen, mehrere davon Fortune-500-Umgebungen, ausgelöst von Agenten auf Anthropics Claude, OpenAIs Codex und Nous Researchs Hermes. Bruce Schneier griff die Studie am 4. September auf und las sie so, wie sie es verdient: Die Grenze zwischen Daten und ausführbarem Code löst sich auf. Ein in diesem Beitrag zitierter Forscher braucht weniger Worte. „Das Vertrauensmodell ist kaputt.“ Agenten „behandeln Anbieterdokumentation als Grundwahrheit und hinterfragen sie nicht“.

Clerk dokumentierte ein Paket, das es nie ausgeliefert hat

Das klarste Beispiel kommt von einem Authentifizierungsanbieter, dessen Dokumentation dem Leser sagt, er solle Folgendes ausführen:

npx clerk-next-fix-auth-protection

Clerk hat nie ein eigenständiges Paket unter diesem Namen veröffentlicht. Vielleicht war der Befehl eine Abkürzung, vielleicht zeigte er auf etwas Internes, vielleicht hat sich ein Autor vertan. Der Grund spielt keine Rolle, denn für einen Agenten las sich der Name echt. Jemand anderes hat ihn registriert. Advisory-Datenbanken führen dieses Paket inzwischen als MAL-2026-11069, und es tat, was man für Aufklärung baut: Die npm-Installationshooks feuerten und schickten den Benutzernamen des installierenden Kontos, den Hostnamen der Maschine, das Arbeitsverzeichnis und einen Zeitstempel hinaus.

Das ist eine Karte der Build-Umgebung von jemandem, gesammelt innerhalb seines Netzwerks durch seinen eigenen Coding-Agenten, der der Doku seines eigenen Anbieters folgte.

Fünf gewöhnliche Schritte, nirgends eine Kompromittierung1 · der Anbieter publiziertvendor.com/llms.txtfür Agenten, nicht für Menschennpx clerk-next-fix-auth-protection2 · der Name ist freies wurde nie ein Paketunter diesem Namen publiziert237 solcher Namen in 120 Dateien3 · jemand nimmt ihnein ganz normaler npm-PublishMAL-2026-11069Payload steckt in den Install-Hooks4 · der Agent liest das Doc und glaubt esClaude, Codex und Hermes wurden alle beim Install beobachtetder Befehl kam von der eigenen Domain des Anbieters, nichts zu bezweifelnkein Credential gestohlen · kein Repo kompromittiert · kein Maintainer gephisht5 · die Hooks funken heimBenutzername · HostnameArbeitsverzeichnis · Zeitstempeleine Karte der Build-UmgebungDie einzige echte Arbeit des Angreifers war, eine Datei zu lesen, die der Anbieter des Opfers absichtlich publiziert hat.
In der Kette steckt keine Kompromittierung. Ein Anbieter veröffentlicht ein maschinenlesbares Dokument, das einen Installationsbefehl nennt; das Paket wurde nie veröffentlicht, also bleibt der Name in der Registry frei; ein Angreifer registriert ihn; der Agent holt das Dokument als Grundwahrheit und führt die Installation aus; die Installationshooks melden die Umgebung zurück. Jedes Glied ist eine ganz normale, korrekt ausgeführte Operation.

Warum der übliche Rat direkt auf die Payload zeigt

Jeder Supply-Chain-Leitfaden sagt Ihnen, Sie sollen einen Paketnamen gegen die offizielle Dokumentation prüfen. Dieser Rat versagt hier, denn die offizielle Dokumentation ist genau der Ort, aus dem der schlechte Name stammt.

Drehen Sie das Problem um, über das wir im Juli geschrieben haben, und Sie bekommen dieses. Dort halluziniert ein Agent einen plausiblen Paketnamen, und ein Angreifer registriert die Namen, die er zu erfinden pflegt, der schwache Schritt ist also die Vermutung des Modells. Hier vermutet das Modell nichts. Es geht zum Anbieter, liest, was der Anbieter sagt, folgt dem, und genau diese sorgfältige Abfolge erwischt es.

Eine Registry-Kompromittierung hat ebenfalls eine andere Form. Als ein Release-Workflow zehn vergiftete Versionen eines echten Pakets veröffentlichte im vergangenen Monat, musste erst etwas brechen: ein Workflow, der einem Kommentar vertraute. Hier bricht nichts. Ein Technischer Redakteur tippt einen Befehl, der nicht ganz zu einem veröffentlichten Artefakt passt, was der gewöhnlichste Fehler der Softwarewelt ist, und die Lücke zwischen Name und Artefakt wird zu einem Ausführungsprimitiv, das jeder im Internet aufheben kann.

Was der Scan fand, und wie schnell der Beweis kam6.214aktive Domains gescanntFortune 500, Tech, Rüstung8.000+Doc-Dateien für Agentenllms.txt · llms-full.txt120Dateien nennen etwas,das nie registriert wurde237freie Namen, 6 Registriesdazu Vercel, Render, Fly, Netlifydann registrierten sie eine Stichprobe und wartetenerster Installations-Rückruf aus einer Fortune-500-Umgebungunter 4 Minutenzweiter Rückrufbinnen einer Stunde · Dutzende Organisationen
Der Trichter aus der Studie. Von 6.214 Firmendomains mit agentengerichteter Dokumentation nannten 120 Dateien etwas Unregistriertes, zusammen 237 freie Namen. Eine Stichprobe davon zu registrieren erzeugte einen Installations-Rückruf aus einem Fortune-500-Netz in unter vier Minuten.

Die Schicht, die das abfängt, ist schon an

Bromure Agentic Coding führt jeden Coding-Agenten in einer hardwarevirtualisierten Linux-VM auf Ihrem Mac aus, und jedes Paket, das der Agent holt, läuft durch einen Proxy auf der Host-Seite dieser Grenze, bevor ein einziges Byte die VM erreicht. Dort greifen mehrere Schichten. Für diese Geschichte erledigt eine davon die Arbeit im Alleingang, und es ist genau die, die ein neuer Arbeitsbereich bereits eingeschaltet hat.

Die Altersschwelle macht aus einem frisch belegten Namen ein Nicht-Ereignis. Ein Arbeitsbereich verweigert Paketversionen, die jünger sind als eine Grenze, die ab Werk bei zwei Tagen liegt. Der Proxy setzt das durch, indem er die Versionsliste der Registry im Vorbeigehen umschreibt: Er entfernt Versionen, die jünger als die Grenze sind, und zeigt latest neu auf die jüngste Überlebende. Ein Paket, das heute Morgen zum ersten Mal veröffentlicht wurde, hat keine Version, die alt genug wäre, um diesen Filter zu überstehen, aus Sicht des Agenten gibt es unter diesem Namen also nichts zu installieren. Fragt der Agent direkt nach einer zu frischen Version, kommt der Abruf als HTTP 451 zurück, dessen Body das echte Alter des Pakets und das geforderte Minimum nennt, und npm gibt diesen Text wortwörtlich aus.

Lesen Sie den Angriff mit diesem Baustein noch einmal. Die gesamte Technik hängt daran, dass ein Name zu einem vom Angreifer gewählten Zeitpunkt von unpubliziert zu publiziert wechselt. Dieser Übergang ist ein brandneues Release. Die eine Eigenschaft, der der Angreifer nicht ausweichen kann, ist genau die, an der die Standardrichtlinie ansetzt.

Das Entfernen von Installationsskripten nimmt genau den Mechanismus weg, den die Payload nutzte. Das beobachtete Paket erledigte seine Arbeit in den npm-Hooks preinstall, install, postinstall und prepare. Mit aktiviertem Skript-Stripping entpackt der Proxy jedes npm-Tarball im Flug, löscht diese vier Schlüssel aus der package.json, entfernt dist.integrity und dist.shasum aus den Metadaten, damit npms eigene Hash-Prüfung weiterhin durchgeht, und packt wieder ein. Das Paket installiert sich; das Beacon hat nichts mehr, woraus es starten könnte. Pakete, die ihre Hooks brauchen, etwa Compiler nativer Bindings wie better-sqlite3, kommen auf eine Allowlist pro Arbeitsbereich und behalten sie.

Die Reputationsfilterung kennt dieses Paket beim Namen. MAL-2026-11069 ist ein Malware-Advisory. Mit socket.dev als gewähltem Paketfilter des Arbeitsbereichs greift dessen Sperre für kompromittierte Pakete bei Malware- und Typosquat-Signalen in jeder Schwere; die kostenlose OSV-Prüfung deckt alle acht abgefangenen Ökosysteme ohne API-Schlüssel ab. Wenn eine Reputationsquelle kein Urteil liefern kann, sei es durch Rate Limiting, ein weggebrochenes Netz oder ein Ökosystem, das sie nicht abdeckt, fällt Bromure geschlossen aus, statt den Abruf zuzulassen. Der Download pausiert und fragt Sie, pro Paket und Version, sodass ein Angreifer, der einen Abfragefehler auslösen kann, nichts gewinnt.

Die Aufklärung, die es einsammelt, gehört der VM. Jede Schlagzeile zu dieser Studie sagt dasselbe: Agenten installieren unbekannten Code in Unternehmensnetzen. Die Ernte des Beacons war der installierende Benutzername, der Hostname der Maschine und das Arbeitsverzeichnis. In einem Bromure-Arbeitsbereich beschreiben diese drei Felder einen Linux-Gast auf Ihrem Mac und nicht einen domänengebundenen Build-Host mit einem internen Namen, der sich für eine Zielliste lohnt. Die Zugangsdaten, die in dieser VM liegen, sind Attrappen, deren echte Werte nur im Speicher des Host-Proxys existieren. Versucht feindlicher Code doch, eine davon zu einem Host zu tragen, für den sie nicht geprägt wurde, blockiert der Proxy die Anfrage und pausiert die VM mitten im Flug.

Default Deny beantwortet die andere Hälfte der Studie. Etliche der freien Namen waren Hostnamen statt Paketen: abgelaufene Domains und kostenlose Subdomains bei Vercel, Render, Fly und Netlify, die in Dokumenten stehen, die Agenten abrufen. Die Egress-Firewall des Arbeitsbereichs ist eine geordnete Regeltabelle mit einer Einstellung Unmatched traffic; setzen Sie sie auf Deny, und die VM öffnet Verbindungen zu den von Ihnen gelisteten Hosts und zu nichts sonst, auf jedem Protokoll. Zwei Komponenten setzen das außerhalb des Gastes durch: Der virtuelle Netzwerk-Switch prüft jeden Fluss anhand der Ziel-IP-Adresse, und der Host-Proxy prüft noch einmal anhand des TLS-Servernamens. Ein Beacon, das auf eine Domain zielt, die jemand vergangenen Dienstag registriert hat, verlässt die Maschine nicht. Regeländerungen erreichen laufende Sitzungen ohne Neustart.

Jeder Versuch bekommt eine Zeile. Auf der Trace-Stufe Activity only schreibt der Proxy einen Metadatensatz pro Anfrage aus der VM, mit Zeitstempel, Host, Port, Methode, Pfad, Status, Latenz und Bytes, und er speichert überhaupt keine Request-Bodies. bromure-cli trace hostnames my-workspace gibt jeden einzelnen Host aus, den der Arbeitsbereich kontaktiert hat, mit Zählern. Sie sehen eine Rückruf-Domain, die keiner Ihrer Ingenieure kennt, an dem Tag, an dem es passiert, auf Ihrer eigenen Maschine, statt Monate später im Datensatz eines Fremden davon zu lesen.

Ein Agent auf einem Entwicklerrechnernpx clerk-next-fix-auth-protectiondirekt aus dem Doc des Anbieterswas danach passiert, alles im Netzwerkdie Registry liefert, was publiziert wurde, egal wie neupostinstall läuft mit der Identität des EntwicklersBenutzername, Hostname und cwd sind Firmenfaktender Rückruf geht, wohin er willkein Eintrag pro Anfrage über das Zielder Install klappt und sieht aus wie jeder andereInstall, den der Agent an dem Nachmittag fuhrErster Rückruf: unter vier Minuten.Sie erfahren davon, wenn ein Fremder die Studie publiziert.Ein Bromure-Agentic-Coding-Arbeitsbereichnpx clerk-next-fix-auth-protectionderselbe Befehl, aus demselben Docwas danach passiert, alles auf dem HostAltersschwelle: Versionen unter zwei Tagen fliegen rausein heute genommener Name hat nichts InstallierbaresStrip: die vier Install-Hooks werden entferntBenutzername, Hostname und cwd sind eine Linux-VMnicht zugeordneter Egress verweigert, per Ziel-IPdie Ablehnung ist ein 451, den der Agent lesen kann,plus eine Zeile im Security Log mit dem echten AlterErster Rückruf: keiner.Sie erfahren es vom eigenen Rechner, am selben Tag.
Links: Die Installation läuft auf einem Entwicklerrechner im Unternehmensnetz, die Registry wird direkt befragt, die Installationshooks laufen mit der Identität des Entwicklers, und der Rückruf geht ohne Eintrag hinaus. Rechts: derselbe Befehl, geführt durch einen Proxy auf der Host-Seite, der die frisch veröffentlichte Version aus den Metadaten filtert, die Hooks entfernt, falls es überhaupt so weit kommt, nicht zugeordneten Egress verweigert und für jede Anfrage eine Zeile schreibt.

Was schon an ist

Ein neuer Arbeitsbereich kommt mit aktivierter Altersschwelle bei einem Minimum von zwei Tagen, und genau in diese Einstellung läuft dieser Angriff. Heben Sie sie an, wenn Ihre Arbeit das Warten verträgt, bis zu 90 Tage auf dem Stepper, und nutzen Sie Exempt packages für die Pakete, die Ihr eigenes Team in derselben Stunde veröffentlicht und installiert, in der Form npm:unser-paket.

Was sich heute einzuschalten lohnt

Aktivieren Sie im Bereich Supply Chain des Arbeitsbereichs das Entfernen von Installationsskripten und wählen Sie einen Paketfilter. Setzen Sie unter Guardrails Unmatched traffic auf Deny und listen Sie die Hosts, die der Job braucht. Unter Tracing behält Activity only die Spur der kontaktierten Hosts und nichts vom Inhalt. Jede dieser Änderungen gilt für bereits laufende Sitzungen.

Niemand liest eine Datei Korrektur, die für Maschinen geschrieben ist

Der PANDEX-Scanner jagt noch etwas. Neben unbeanspruchten Paketen und Domains sucht er nach Anweisungen, die an den Agenten statt an den Leser gerichtet sind: Direktiven, die in die Datei gepflanzt wurden, manchmal mit Unicode-Tricks und Zeichen der Breite null versteckt. Die Build-Pipeline eines Anbieters erzeugt llms.txt, Ihr Agent konsumiert es, und niemand in einer der beiden Firmen liest, was da zwischen ihnen hin und her ging.

Bromure behandelt eine abgerufene Seite als nicht vertrauenswürdige Eingabe. Inhalte, die der Agent von außen hereinzieht, seien es Dateiinhalte, Webseiten, Issue-Texte oder Kommandoausgaben, erreichen das Modell als tool_result-Span. Mit aktiviertem Quellcode-Detektor bewertet ein PromptGuard-Modell auf Ihrem Mac diese Spans auf der Leitung, bevor das Modell darauf handelt, und Sie entscheiden, ob es protokolliert, fragt oder blockiert. Kein Inhalt geht irgendwohin, um geprüft zu werden.

Wir haben ein Jahrzehnt damit verbracht zu lernen, Artefakte zu verifizieren: das Paket signieren, den Hash pinnen, den Build attestieren. Diese Studie handelt vom Schritt davor, dort, wo ein Agent entscheidet, nach welchem Artefakt er fragt, und dabei von einem Dokument ausgeht, das keine Signatur trägt und von einem technischen Redakteur in Eile geschrieben wurde. Dokumentation ist zu einer ausführbaren Eingabe geworden, und die Registries sind voll freier Namen, die darauf warten, dass jemand bemerkt, dass ein Anbieter sie erwähnt hat.

Greppen Sie Ihre eigene llms.txt nach Namen, die Sie nie veröffentlicht haben. Das ist die Arbeit eines Vormittags und nimmt Sie von der Zielliste eines anderen. Geben Sie Ihrem Agenten dann eine Maschine, auf der ein vor vier Minuten veröffentlichtes Paket nicht installierbar ist und auf der Sie sehen können, wohin er überall gegangen ist. Installieren Sie Bromure Agentic Coding und legen Sie den Installationspfad auf den Host.