Der gelöschte Schlüssel stand noch in der History
Am 8. Oktober hat eine Kampagne namens GhostAction zwei gekaperte Maintainer-Konten genutzt, um einen Workflow namens security-audit.yml in 346 Repositories zu committen, darunter Ubers athenadriver und pyxel mit 18.000 Sternen. Am 9. Oktober zählte Socket mehr als 500 Konten und Zehntausende Repositories. Der Workflow führt git log -p --all aus und durchsucht jeden jemals gemachten Commit nach Schlüsseln für Anthropic, OpenAI, OpenRouter, GitHub und AWS, auch nach denen, die einen Commit später gelöscht wurden. In Bromure Agentic Coding hält der Agent immer nur Platzhalter, also sind die Schlüssel, die er in die History eines Repositorys schreibt, für den Finder nichts wert.
Einen Schlüssel aus einer Datei zu löschen kostet einen Commit. Der Commit davor behält den Schlüssel, solange das Repository existiert.
Am Donnerstag, dem 8. Oktober, um 13:40 UTC begann das GitHub-Konto von
Takashi Kitao, Autor der Game-Engine pyxel, eine Datei namens
.github/workflows/security-audit.yml zu committen. Vier Minuten später lag
sie in 27 seiner Repositories. Um 21:10 UTC startete das Konto henrywoo,
ursprünglicher Autor von Ubers athenadriver, denselben Durchlauf. Um 21:26
hatte es 318 Repositories erreicht, darunter 279 Forks und uber/athenadriver
selbst, wo das Konto Schreibrechte hat.
Socket veröffentlichte seine
Analyse am 9. Oktober
und ordnete die Commits GhostAction zu, einer Kampagne zum Diebstahl von
Zugangsdaten, die erstmals im September 2025 auftauchte. Bis zum Ende dieses
Tages zählte Socket in einem Update mehr als 500 GitHub-Konten, die den
Workflow seit dem 7. Oktober in „Zehntausende Repositories“ committet hatten.
The Hacker
News
und StepSecurity berichteten über dieselbe Welle. Socket stellte fest, dass
der Workflow in betroffenen Repositories bereits gelaufen war und zum
Zeitpunkt der Veröffentlichung noch auf den Default-Branches von
kitao/pyxel und uber/athenadriver lag.
Was security-audit.yml tut
Der Workflow heißt „Security Audit“. Er läuft bei workflow_dispatch und bei
jedem Push auf einen beliebigen Branch oder Tag, ohne Filter. Sein
Checkout-Schritt verwendet fetch-depth: 0 und holt damit jeden Branch, jeden
Tag und die vollständige History. Dann erledigt ein einziger Schritt zwei
Aufgaben.
Die erste zielt auf die GitHub-Actions-Secrets des Repositorys. Bevor der
Angreifer den Workflow committete, las er die vorhandenen Workflows des
Repositorys und schrieb die Namen der dort verwendeten Secrets in den
Payload. Bei pyxel waren das CARGO_REGISTRY_TOKEN, PERSONAL_ACCESS_TOKEN,
PYPI_PASSWORD und PYPI_USERNAME.
Die zweite ist neu in dieser Welle. Der Schritt durchsucht den Arbeitsbaum
mit grep nach 13 Mustern für Zugangsdaten, führt dann git log -p --all aus
und durchsucht bis zu 200.000 Zeilen History nach denselben Mustern:
- KI-Dienste: Anthropic (
sk-ant-), OpenAI-Projektschlüssel (sk-proj-), OpenRouter (sk-or-) - Versionsverwaltung: klassische GitHub-Tokens (
ghp_), Fine-grained Tokens (github_pat_), GitLab-Tokens (glpat-) - AWS: Access-Key-IDs, temporäre Key-IDs, Secret Keys und Session-Tokens. Der Schritt behält außerdem zwei Zeilen Kontext um jede Key-ID herum, sodass der daneben committete Secret Key mitkommt.
- SaaS und Cloud: Google-API-Schlüssel, Slack-Tokens, SendGrid-Schlüssel
Alles geht in einem einzigen curl-POST über unverschlüsseltes HTTP an
193.32.204.199. Jeder Lauf meldet den Namen des Repositorys, ob er etwas
gefunden hat oder nicht.
Socket benennt die Zielgruppe. Zwei der Repositories von henrywoo sind
pyllama und chatllama, Machine-Learning-Projekte, deren Mitwirkende und
Forker „wahrscheinlich genau diese Schlüsseltypen besitzen“. Ein Anthropic-
oder OpenAI-Schlüssel lässt sich als abrechenbare Inferenz weiterverkaufen,
und jeder Prompt, der darüber läuft, geht durch die Hände des Käufers.
Die History behält alles
Socket gibt bei der Bereinigung einen Rat, der jeden beunruhigen sollte, der
einen geleakten Schlüssel schon einmal durch das Bearbeiten einer Datei
beseitigt hat: „Rotieren Sie alle Zugangsdaten, die in irgendeinem Commit
gefunden werden, ob sie noch im aktuellen Baum stehen oder nicht.“ Ein
Schlüssel, der im nächsten Commit entfernt wird, steht weiterhin im Commit
davor. git log -p --all liest beide.
Coding-Agents füllen diese History schnell. GitGuardians State of Secrets Sprawl 2026 ergab, dass öffentliche Commits, die Claude Code mitverfasst hatte, in 3,2 % der Fälle Secrets leakten, gegenüber einem Grundwert von 1,5 % auf dem gesamten öffentlichen GitHub. Derselbe Bericht zählte für 2025 1.275.105 geleakte Secrets, die an KI-Dienste gebunden waren, 81 % mehr als im Vorjahr.
Das Muster kennt jeder, der einem Agenten dabei zugesehen hat, wie er einen
fehlschlagenden Integrationstest grün macht. Der Agent hat den Schlüssel in
seiner Umgebung. Er schreibt ihn in eine Konfigurationsdatei, eine
Test-Fixture oder eine .env, die noch nicht ignoriert wird, weil der Test
dann durchläuft. Er committet. Später verschiebt der Entwickler oder der
Agent den Schlüssel in eine Umgebungsvariable und committet erneut. Der Baum
sieht sauber aus. Die History enthält den Schlüssel, jeder Fork hat die
History, und ein Workflow mit fetch-depth: 0 liest sie.
Das Token, das den Workflow schrieb
Socket hat nicht ermittelt, wie die beiden Konten übernommen wurden. The
Hacker News nennt die wahrscheinlichste Quelle: ein Personal Access Token aus
Infostealer-Logs oder Credential-Dumps. Infostealer-Logs stammen von
Entwicklerrechnern. Auf einem Laptop liegt das GitHub-Token in
~/.config/gh/hosts.yml, in ~/.git-credentials und oft in GH_TOKEN,
lesbar für alles, was unter dem Konto des Entwicklers läuft, einschließlich
allem, was ein Coding-Agent installiert oder ausführt.
Ein Token genügt. Damit kann der Angreifer die Repositories auflisten, in die
das Konto schreiben darf, ihre Workflows nach Secret-Namen durchlesen und in
jedes davon committen. Der Durchlauf von henrywoo erfasste 318 Repositories
in 16 Minuten.
Dasselbe Repository, geschrieben von einer Bromure-Maschine
In Bromure Agentic Coding läuft der Agent in einer Linux-VM auf Ihrem Mac, und jede HTTP-Anfrage der VM passiert einen Proxy auf dem Host. Ihr Anthropic-Schlüssel, Ihr GitHub-Token und Ihre AWS-Schlüssel bleiben verschlüsselt auf dem Mac. Lassen Sie GhostAction nun auf ein Repository los, das eine Bromure-Maschine geschrieben hat, und auf den Entwickler, der es geschrieben hat.
Die History enthält Platzhalter
In der VM ist jedes Zugangsdatum ein Platzhalter in der Form des echten:
ANTHROPIC_API_KEY ist sk-ant-api03-brm-…, ein OpenRouter-Schlüssel ist
sk-or-v1-brm-…, GH_TOKEN und ~/.git-credentials enthalten ghp_ plus
36 Zeichen. Jeder wird mit HKDF-SHA256 aus dem echten Wert und einem Salt pro
Installation abgeleitet und lässt sich nicht in ihn zurückverwandeln. Der
Proxy setzt den echten Wert erst auf der Leitung ein, und nur für eine Anfrage
an den Host, zu dem das Zugangsdatum gehört.
Wenn der Agent also seinen Schlüssel in config/test.py schreibt, damit der
Test durchläuft, schreibt er, was er hat. Wenn er committet, enthält der
Commit sk-ant-api03-brm-…. Wenn später der Aufräum-Commit kommt, behält die
History genau diesen Platzhalter.
GhostActions grep findet ihn. sk-ant- passt auf sk-ant-api03-brm-, und
ghp_ passt auf einen GitHub-Token-Platzhalter. Der POST an
193.32.204.199 nimmt sie mit, und der Käufer probiert sie aus. Anthropic
lehnt den Schlüssel ab und GitHub das Token, denn das Einzige, was sie in
funktionierende Zugangsdaten verwandelt, ist der Proxy auf Ihrem Mac, für
Anfragen, die Ihre VM verlassen. Socket rät, jeden in irgendeinem Commit
gefundenen Schlüssel zu rotieren. Für dieses Repository ist die Antwort kurz:
Keiner dieser Schlüssel hat außerhalb Ihres Macs je funktioniert, und die
Platzhalter für KI-Anbieter tragen -brm- im Namen, sodass Sie sie bei einem
Scan der History erkennen.
Auch das Token auf dem Laptop ist ein Platzhalter
Die andere Hälfte der Kampagne ist das Konto selbst. Lassen Sie Ihre Agents
in einer Bromure-Maschine laufen, und das GitHub-Token, das sie verwenden,
liegt auf dem Mac. Alles, was in der VM läuft, ob das Installationsskript
eines Pakets, ein Stealer oder eine Prompt-Injection, findet in
~/.git-credentials und GH_TOKEN einen ghp_-Platzhalter. Ein Angreifer,
der ihn von seinem eigenen Rechner aus abspielt, bekommt von GitHub eine 401.
Der Stealer muss seine Beute auch irgendwohin schicken, und diese Anfrage
passiert den Proxy. Ein Platzhalter hat genau ein legitimes Ziel: den Host,
für den er erzeugt wurde. Der Proxy durchsucht jede ausgehende Anfrage,
Header und Body, nach jedem Platzhalter, der woandershin unterwegs ist. Ein
ghp_-Token auf dem Weg zum Server eines Stealers bekommt HTTP 451, nichts
wird weitergeleitet, die VM pausiert, und auf dem Mac öffnet sich This
environment may have been compromised mit einer Vorschau des Tokens, dem
Namen des Zugangsdatums, dem Host, zu dem es gehört, und dem Host, an den es
gesendet wurde.
Ein Workflow-Push wartet auf einen Klick
Würmer dieser Familie warten nicht immer auf einen Käufer. Der
tensorlake-Payload hat letzte
Woche Dateien direkt vom Rechner des Entwicklers in die Repositories seiner
Opfer committet. Neue Bromure-Maschinen verwenden Prompt before write für
jede Git-Forge. Ein Push ist ein Schreibvorgang, also hält das Committen von
security-audit.yml in ein Repository aus der VM an einem macOS-Dialog an,
Allow write on "github.com" from workspace "…"?, der
POST /owner/repo.git/git-receive-pack so zeigt, wie es über die Leitung
ging. Der Durchlauf von henrywoo machte 318 solcher Schreibvorgänge in 16
Minuten. Von einer Bromure-Maschine aus wartet der erste auf Sie, und Sie
haben Ihren Agenten nicht gebeten, 318 Repositories ein Security-Audit
hinzuzufügen.
Jede Verwendung des Tokens wird protokolliert
Die Security Timeline protokolliert jeden Austausch eines Zugangsdatums
als Credential brokering-Zeile: welches Token, welcher Host, welche
Maschine, zu welcher Zeit. Wenn Sie wissen müssen, ob Ihr GitHub-Token am
8. Oktober zwischen 21:10 und 21:26 etwas gepusht hat, liegt die Antwort auf
Ihrem Mac, in einem Protokoll, das der Agent nicht bearbeiten kann. Mit
aktiviertem Tracing listet bromure-cli trace leaks jede Anfrage auf, in der
ein Token beim falschen Host aufgetaucht ist.
Aufräumen nach einem Schlüssel
Der übliche Rat nach einem geleakten Schlüssel lautet: rotieren, die History
mit git filter-repo umschreiben, force-pushen und hoffen, dass kein Fork
und kein Mirror die alten Commits vorher kopiert hat. GhostAction zeigt,
warum der letzte Teil scheitert. Socket zählte 279 Forks in einem einzigen
Namespace, jeder mit der History und inzwischen auch dem Workflow. Ein
Schlüssel, der einen öffentlichen Commit erreicht hat, ist verloren, egal
was der aktuelle Baum zeigt.
Eine Bromure-Maschine ändert, was überhaupt im Commit landet. Der Agent darf
so nachlässig mit Schlüsseln umgehen, wie GitGuardians Zahlen es Agents
nachsagen. Er kann einen Schlüssel in eine Fixture kopieren, eine .env
committen und sie vergessen. Er hatte nie einen funktionierenden Schlüssel,
also kann Ihnen nichts in dieser History schaden.
Der Commit enthält einen Platzhalter
Agents in der VM sehen nur Platzhalter in der Form der echten Schlüssel.
Ein in eine Datei geschriebener und committeter Schlüssel ist ein
-brm--String, der nur über den Proxy auf Ihrem Mac funktioniert.
Die Ernte bringt 401er
GhostActions Muster finden die Platzhalter und schicken sie hinaus. Anthropic, OpenAI und GitHub lehnen sie überall außerhalb Ihres Macs ab.
Ein gestohlenes Token stoppt die Maschine
Auch das GitHub-Token in der VM ist ein Platzhalter. Wird es anderswohin als zu GitHub geschickt, bekommt es eine 451, die VM pausiert, und ein Alarm nennt das Token und den Host.
Pushes warten auf einen Klick
Prompt before write hält jeden Push aus der VM an einem macOS-Dialog an, der die Anfrage zeigt, und die Security Timeline protokolliert jede Verwendung des Tokens.
Das nächste grep
Das ist die dritte Welle von GhostAction in dreizehn Monaten. Die erste, im September 2025, erbeutete 3.325 CI-Secrets. Die zweite, vom 31. August bis 30. September dieses Jahres, zielte auf 2.577 Secrets in 772 Repositories. Diese hier hat die vollständige History und drei Muster für KI-Anbieter hinzugefügt. Die nächste Welle wird weitere Muster hinzufügen, und die History, die sie liest, wächst nur.
Lassen Sie Ihre Agents dort laufen, wo die Schlüssel, die sie anfassen, Platzhalter sind, und die History, die sie hinterlassen, enthält nichts, was ein Käufer verwenden kann. Mehr dazu, wie Platzhalter funktionieren und was passiert, wenn einer leakt, lesen Sie in Der Agent leakte seinen eigenen Schlüssel und Der Schlüssel ist nie abgelaufen.