Eine Sitzung, hundert Repositories
Mandiants Bericht AI Risk and Resilience 2026 beschreibt einen Angreifer, der bei einem SaaS-Anbieter eine laufende Sitzung eines KI-Coding-Assistenten übernahm, darüber ein vergiftetes PyPI-Paket installieren ließ, GitHub-OAuth-Tokens stahl und den Shai-Hulud-Wurm über rund 100 interne Repositories verteilte. Der Bericht sagt nicht, wie die Sitzung übernommen wurde. In einem Bromure-Agentic-Coding-Workspace muss er das auch nicht: Das Token in dieser Sitzung ist ein `ghp_`-Köder, der Versuch, es hinauszuschicken, pausiert die VM, und die Pushes, die aus einer Maschine hundert Repositories machen, enden am Proxy des Hosts.
Jemand übernahm eine Coding-Sitzung, die lief, authentifiziert und vertrauenswürdig, auf der eigenen Maschine eines Entwicklers. Alles, was danach kam, bis hin zu hundert Repositories, stammte aus dem, was diese Maschine in diesem Moment bei sich trug.
Ein Entwickler bei einem Software-as-a-Service-Unternehmen fragte seinen
Coding-Assistenten, welches Paket er für ein ganz gewöhnliches Problem nehmen
solle. Der Assistent nannte eines. Der Entwickler sagte ja, was genau der Sinn
eines Assistenten ist, und pip install erledigte den Rest.
Ein Angreifer hatte die Sitzung da längst, und er war es, der diese Empfehlung tippte.
Mandiant beschreibt den Fall im AI Risk and Resilience Report 2026, in diesem Monat veröffentlicht von der Incident-Response-Sparte von Google Cloud; The Hacker News berichtete am 16. September darüber. Der Angreifer kaperte eine aktive Coding-Assistenten-Sitzung auf der Workstation eines Entwicklers. Fünf weitere Schritte brachten ihn zu rund hundert internen Code-Repositories und zum Paket-Namensraum des Unternehmens, wo ein zweiter Mitarbeiter die vergiftete Version zog.
Die Kette, Schritt für Schritt
Mandiant hält genau den Teil zurück, den man am dringendsten wissen möchte. Die öffentliche Fallstudie sagt nicht, wann der Einbruch stattfand, und sie sagt nicht, wie der Angreifer die Kontrolle über eine laufende Sitzung bekam. Gestohlene Browser-Cookies, eine bösartige Erweiterung, eine kompromittierte CLI auf einer gemeinsam genutzten Maschine: Der Bericht entscheidet sich für keines davon. Wer ihn liest, um den Patch zu finden, geht ohne einen wieder.
Die Schritte 2 bis 6 enthalten überhaupt keinen Exploit. Eine Paketinstallation
funktioniert so, wie Paketinstallationen funktionieren, und Code, der als der
Entwickler läuft, liest die Tokens, die auf der Platte des Entwicklers liegen.
Ein git push mit gültigem Token pusht, und eine Veröffentlichung mit gültigen
Veröffentlichungsrechten veröffentlicht. Ein Schritt war ein Einbruch; die
anderen fünf waren Ausgeben.
Der Multiplikator sind Zugangsdaten, und er wächst weiter
Shai-Hulud ist der selbstreplizierende Supply-Chain-Wurm, der seit 2025
Maintainer-Konten frisst, und er taucht in einer Geschichte wie dieser als
Payload auf, weil Schritt 5 genau das ist, wofür seine Autoren ihn gebaut
haben. GitGuardian hat im August eine neuere Variante auseinandergenommen und
fand sie beim Absuchen von 469 Fundorten für Zugangsdaten,
gegenüber 189 in früheren Builds: Entwicklungsumgebungen, CI/CD-Werkzeuge,
Cloud-Konfiguration, Konfigurationen von KI-Werkzeugen,
Paketmanager-Konfigurationsdateien, Shell-History, .env-Dateien,
IDE-Einstellungen, CLI-Caches. Der Wurm liest einen Aktenschrank, statt nach
einer Lücke zu jagen.
GitGuardians Analyse fasst die Kategorie in einem Satz zusammen:
„Angreifer haben aufgehört zu versuchen, Vertrauensbeziehungen zu brechen, und begonnen, die Zugangsdaten zu benutzen, die diese Beziehungen ohnehin funktionieren lassen.“
Aus einer Workstation wurden hundert Repositories, weil sie Berechtigungen im Wert von hundert Repositories bei sich trug. Diese Zahl kam aus einem Inventar, und Sie entscheiden, was in das Inventar hineinkommt.
Die Sitzung trug Köder bei sich
Bromure Agentic Coding führt den Agenten in einer virtuellen Linux-Maschine auf Ihrem Mac aus, und diese Maschine trägt keine echten Geheimnisse. Sie schalten dafür nichts ein. So speichert ein Workspace Zugangsdaten, von vornherein.
Ihr echtes GitHub-Token bleibt verschlüsselt auf dem Host. Die VM bekommt eine
strukturerhaltende Fälschung: ghp_ gefolgt von 36 Zeichen, 40 insgesamt,
sodass die Präfix- und Längenprüfungen von gh selbst anstandslos bestehen.
Bromure exportiert sie als GH_TOKEN und schreibt sie in ~/.git-credentials
und in die gh-Konfiguration, und sie sind die einzigen GitHub-Zugangsdaten in
dieser Maschine überhaupt. Ein Proxy auf dem Host setzt den echten Wert erst
auf der Leitung ein, nachdem die Anfrage die VM verlassen hat, und nur, wenn
das Ziel zu dem Host passt, für den die Zugangsdaten geprägt wurden. Jede
Fälschung ist deterministisch, aus dem echten Wert plus einem
installationseigenen 32-Byte-Salt über HKDF-SHA256 abgeleitet, sodass ein
Client, der den Fingerabdruck seines eigenen Schlüssels bildet, zwischen
Sitzungen keine scheinbare Rotation sieht.
Lassen Sie Schritt 4 dagegen laufen. Der Infostealer kommt an, durchsucht die
469 Fundorte, findet die Umgebungsvariable, findet ~/.git-credentials, findet
die gh-Konfiguration und verschickt, was er gefunden hat. Jeder Lesevorgang
gelingt, und jede Datei liegt da, wo der Wurm sie erwartet hat. Der Angreifer
endet mit einer vierzig Zeichen langen Zeichenkette, die sich nirgends
authentifiziert, außer sie läuft noch einmal durch genau einen bestimmten Mac.
Die Schritte 5 und 6 brauchen beide, dass Schritt 4 ein funktionierendes Token hervorgebracht hat, und Schritt 4 hat einen Köder hervorgebracht.
Der Diebstahl ist zugleich der Alarm
Ein gefälschtes Token hat genau ein legitimes Ziel. Keine harmlose Anfrage
trägt einen für github.com geprägten ghp_-Köder zu irgendeinem anderen
Host, also durchsucht der Proxy jede ausgehende Anfrage, Header und Body, nach
jeder Fälschung, die ihren eigenen Geltungsbereich verlässt. Er lässt einen
Aho-Corasick-Automaten laufen, billig genug, um ihn auf den gesamten Verkehr zu
richten.
Wenn der Proxy eine findet, tut er mehr, als sie zu protokollieren:
- er weist die Anfrage mit HTTP 451 ab, und kein Byte davon erreicht das Ziel;
- Bromure pausiert die VM auf der Stelle;
- eine Warnung bietet Ihnen Herunterfahren, Für die Untersuchung sichern (Platte, Home und geteilte Ordner zuerst für die Forensik exportieren) oder Fortfahren auf eigenes Risiko;
- die Security Timeline bekommt eine rote Zeile Credential brokering;
- Bromure markiert den Workspace als kompromittiert, sodass der nächste Start das Festplatten-Image und das persistente Home löscht. Ihre Tokens, SSH-Schlüssel und Workspace-Einstellungen überleben dieses Löschen.
Sie schalten davon nichts ein; der Detektor läuft immer. Der Exfiltrationsversuch in Schritt 4 ist das, was die Sitzung stoppt, und so endet der Vorfall mit einer pausierten VM und einem Timeline-Eintrag statt mit hundert Repositories und einer Fallstudie.
Hundert Repositories sind hundert Pushes
Angenommen, Sie wollen Gürtel und Hosenträger. Schritt 5 ist ein Wurm, der in Repositories schreibt, und der Host klassifiziert Schreibvorgänge.
Die Leitplanken eines Workspace tragen eine Schreibrichtlinie
pro Dienst. Für GitHub liest diese Richtlinie git-over-HTTPS ebenso wie die
REST-API: Ein git push kommt als git-receive-pack an und zählt als
Schreibvorgang, während ein git fetch als git-upload-pack ankommt und als
Lesevorgang zählt. Nur Lesen weist die Pushes ab. Vor dem Schreiben
fragen, die Vorgabe für neue Workspaces, hält jeden einzelnen für einen
Dialog auf Host-Seite an, der die Operation benennt. Fetches gehen unter beiden
durch, der Agent arbeitet also weiter.
Der Proxy trifft diese Entscheidung auf dem Host, außerhalb der VM. Ein Agent, dessen Sitzung jemand anderem gehört, kann die Richtlinie weder abschalten noch umgehen, weil die Richtlinie nicht auf der Seite des Agenten läuft. Ein Wurm, der hundert Repositories will, sammelt hundert Ablehnungen ein, oder fragt Sie hundertmal.
Und das Paket musste immer noch ankommen
Schritt 3 ist die Stelle, an der Mandiant konkrete Ratschläge gibt: von der KI empfohlene Drittabhängigkeiten gegen kryptografische Prüfsummen und Allowlists validieren und den Abhängigkeitsverkehr über Repositories leiten, die Sie kontrollieren.
In einem Workspace läuft jeder Paketabruf ohnehin schon über den Host, denn der
Proxy ist der einzige Weg der VM ins Netz. Bromure fängt PyPI unter pypi.org
und files.pythonhosted.org ab und wendet dort die Richtlinie des Hosts an.
Die pip.conf in der VM kann verschärfen, was der Proxy geliefert hat; lockern
kann sie es nicht. Drei Schichten sprechen für Python-Pakete:
- die Altersschranke, standardmäßig an mit einem Minimum von zwei Tagen, die Versionen abweist, die jünger sind als die Grenze, nach der Überlegung, dass ein frisch veröffentlichtes Release dasjenige ist, das am wahrscheinlichsten gerade gekapert wurde. PEP-503-Indizes tragen keine Zeitstempel, also schlägt Bromure den Veröffentlichungszeitpunkt bei Bedarf nach;
- die OSV-Prüfung gegen
api.osv.dev, kostenlos und ohne Schlüssel, die jede Version blockiert, zu der eine Sicherheitsmeldung ab der von Ihnen gewählten Schwere vorliegt; - socket.devs Filter für kompromittierte Pakete, der bei Malware, bekannter Malware, Typosquatting und bösartigen Installationsskripten anschlägt.
Eine Blockade kommt als HTTP 451 zurück, dessen Body mit
Bromure Supply-Chain Security blocked this request: beginnt, gefolgt vom
Grund, und pip gibt das wörtlich aus. Sie sehen, warum die Installation
fehlgeschlagen ist, und der Agent sieht es auch, der oft von selbst eine ältere
Version festnageln kann. Diese ältere Version ist genau die, auf die ihn die
Altersschranke zusteuern wollte.
Mandiants drei Kontrollen, und wo sie wohnen
Der Bericht schließt die Fallstudie mit drei Empfehlungen ab. Jede benennt einen Ort, an dem ein Bromure-Workspace die Grenze bereits zieht.
Von der KI empfohlene Abhängigkeiten validieren
Mandiant verlangt Prüfsummen und Allowlists für alles, was der Assistent vorschlägt. Ihr Workspace wendet seine Richtlinie auf die Antwort der Registry an, bevor die VM sie sieht. Der Proxy streicht zu frische Versionen aus der Versionsliste, sodass sie aus Sicht des Agenten noch gar nicht existieren, und er weist eine festgenagelte, zu frische Version ab und zitiert das echte Alter des Pakets im Fehler. Die Schlüssel für die Reputationsdienste bleiben auf dem Host, außerhalb der Maschine, die die Installation ausführt.
Rohe Schlüssel und langlebige Tokens fernhalten
Das ist die Grenze auf der Leitung, als Ratschlag formuliert. Keine Datei, keine Umgebungsvariable und kein Prozess in der VM trägt einen echten API-Schlüssel, ein echtes OAuth-Token, ein echtes AWS-Secret oder einen echten privaten SSH-Schlüssel. Bromure hält die OAuth-Tokens des Abos verschlüsselt auf dem Host und erneuert sie dort etwa fünf Minuten vor dem Ablauf, sodass der Gast kein Refresh-Token bei sich trägt. Der Kanal zwischen beiden läuft in eine Richtung: Der Host schreibt Fälschungen hinein, und die VM hat keinen Aufruf, mit dem sie ein echtes Token zurückverlangen könnte.
Abhängigkeitsverkehr über etwas leiten, das Sie kontrollieren
Der Proxy ist der einzige Weg der VM nach draußen. Jede HTTPS-Anfrage reist über einen virtuellen Socket zum Host, der das TLS terminiert, die Anfrage inspiziert und sie über den eigenen TLS-Stack von macOS neu absendet. Genau dieser eine Pfad macht die anderen beiden Kontrollen durchsetzbar statt nur empfehlend. Kein Paketabruf kann die Prüfungen überspringen, und keine Zugangsdaten können ungetauscht hinaus.
Und den Explosionsradius absichtlich klein halten
Hundert Repositories fielen, weil eine Maschine Berechtigungen für hundert Repositories trug. Schneiden Sie Workspaces einen pro Projekt zu, oder einen pro Zugangsdaten-Grenze. Jeder bildet auf genau eine VM ab, keine zwei teilen sich eine, und jeder trägt die Zugangsdaten, die die Arbeit in diesem Workspace braucht. Das Inventar einer einzelnen Maschine stellen Sie in einem Einstellungsbereich ein.
Der Teil, den man nicht patchen kann
Mandiant fasst die Kategorie in einen Satz, der eher die Form als den Vorfall beschreibt: „eine vergiftete Datenquelle, eine Modell-Abhängigkeit oder ein Erweiterungs-Hook kann einen vertrauenswürdigen Agenten in einen Kanal für interne Aufklärung, laterale Bewegung oder autonomen Ausbruch aus einer Sandbox verwandeln.“
Drei verschiedene Einstiegspunkte, ein Satz, und er gilt für alle drei. Der Einstiegspunkt bestimmt, wie ein Angreifer ankommt; der Inhalt der Maschine eines Entwicklers bestimmt, wie weit er kommt. Dieser Angreifer kam über eine gekaperte Sitzung herein. Der nächste kommt über etwas anderes herein, und der Bericht nennt Ihnen keine Tür, die Sie abschließen könnten.
Bauen Sie für den Schritt nach dem Einstieg. Nehmen Sie an, die Sitzung gehört bereits jemand anderem, was die Annahme ist, zu der die Fallstudie Sie zwingt, indem sie Schritt 1 nie erklärt, und fragen Sie dann, was diese Sitzung erreichen kann.
Eine Version dieses Vorfalls endet bei Schritt 3, mit einer 451 im Terminal und einer Zeile im Security Log. Eine andere endet bei Schritt 4, mit einer pausierten VM und einer roten Zeile in der Timeline, die festhält, dass Zugangsdaten hinauswollten. Keine der beiden Versionen erreicht Schritt 5, und bei Schritt 5 lagen die hundert Repositories.
Setzen Sie den Agenten auf eine Maschine, die Köder bei sich trägt. Installieren Sie Bromure Agentic Coding, und lassen Sie jemanden die Sitzung nehmen.