Das Paket war wirklich Red Hats
Zwischen Ende Mai und dem 1. Juni 2026 schob ein Wurm namens Miasma credential-stehlenden Code in 32 Pakete unter dem npm-Scope @redhat-cloud-services — Red Hats eigener Namespace, ~117.000 wöchentliche Downloads, signiert von Red Hats echter Publishing-Pipeline. Es gab keinen Typosquat zu erwischen und keinen unbekannten Maintainer zu markieren. Das Vertrauenssignal war der Name des Anbieters auf dem Scope, und der Name des Anbieters ist genau das, worauf der Angreifer hereinritt. Hier ist, warum „bevorzuge seriöse Publisher“ aufhörte, eine Verteidigung zu sein, und was sich ändert, wenn der Agent, der die Installation ausführt, in einer Bromure-VM pro Profil lebt.
Die Supply-Chain-Angriffe, die wir im Mai aufschrieben, hatten ein
Erkennungsmerkmal. Eine Git-URL, wo ein Versionsbereich stehen sollte.
Eine Bun-Laufzeit, die aus dem Nichts auftauchte. Eine optionale
Abhängigkeit, die absichtlich fehlschlug. Miasma hat kein
Erkennungsmerkmal. Die Pakete waren @redhat-cloud-services/sources-client
und einunddreißig seiner Geschwister — echt Red Hats, unter Red
Hats eigenem npm-Scope, veröffentlicht von Red Hats eigener Pipeline mit
gültiger Signatur. Nichts war gefälscht. Der Angreifer musste nichts
fälschen. Der Name auf dem Scope war der ganze Exploit.
Ein Coding-Agent, der @redhat-cloud-services/vulnerabilities-client
auflöst, zögert nicht, und Sie würden es auch nicht. Es ist eine
First-Party-Abhängigkeit von einem der größten Enterprise-Anbieter der
Branche. Es gibt keinen Maintainer zu prüfen, denn der Maintainer ist
Red Hat. Es gibt keinen Namen, bei dem man nach einem vertauschten
Buchstaben schielen müsste, denn der Name ist genau so geschrieben, wie
er sein sollte. Jede Heuristik, die ein sorgfältiger Entwickler oder ein
sorgfältiger Agent anwendet, bevor er npm install ausführt, gibt grün
zurück. Also läuft die Installation, und ein preinstall-Hook feuert,
und der Hook ist ein 4,2 Megabyte großer Blob aus obfuskiertem
JavaScript, der anfängt, das Dateisystem nach Schlüsseln zu durchsuchen.
Der gesamte Vorfall ist eine Demonstration einer unbequemen Tatsache: seriöser Publisher ist keine Sicherheitskontrolle. Es fühlt sich wie eine an. Der Großteil der Supply-Chain-Ratschläge der letzten drei Jahre lehnt sich daran an. Und am 29. Mai kaufte es exakt nichts.
Was Miasma tat.
Die Kampagne — der String Miasma: The Spreading Blight taucht zuerst
in einem Commit vom 29. Mai 2026 auf, laut
OX Security —
wurde von Aikido und OX Security erwischt und
später von Socket, JFrog, Wiz, ReversingLabs, Microsoft und anderen
analysiert. BleepingComputer
und The Hacker News
berichteten beide am 1. Juni darüber.
Die Form, auf ihre Mechanik heruntergebrochen:
- Der Einstiegspunkt war ein kompromittierter GitHub-Account eines
Red-Hat-Mitarbeiters, genutzt, um bösartige Commits in die
@redhat-cloud-services-Quell-Repositories zu schieben. - Ein GitHub-Actions-Workflow trug ein
_index.js-Script, das sich gegenüber npms Trusted-Publishing-Endpunkt mit einem OIDC-Token authentifizierte — derselbe schlüssellose Mechanismus, den npm jetzt gegenüber langlebigen Publish-Tokens empfiehlt. Aus npms Sicht veröffentlichte Red Hats CI Red Hats Pakete. Die Signatur war echt. - Die veröffentlichten Pakete trugen einen
"preinstall": "node index.js"-Hook und eine obfuskierte Nutzlast von rund 4,2 MB. - Bei der Installation durchsuchte die Nutzlast nach GitHub-Actions-
Secrets, AWS-Credentials, Google-Cloud-Credentials, Azure-Service-
Principals, HashiCorp-Vault-Tokens, Kubernetes-Service-Account-Tokens,
npm- und PyPI-Publishing-Tokens, SSH-Schlüsseln, Docker-Credentials,
GPG-Schlüsseln und
.env-Dateien — dann verschlüsselte und exfiltrierte sie, was immer sie fand. - Sie propagierte sich selbst, indem sie den gestohlenen Zugang nutzte,
um über die GitHub-API zu committen,
action.yml-Dateien über GraphQL las und neue Workflows über Mutations zurückschrieb, sodass die Änderungen, in Red Hats eigenen Worten im Commit-Log, verified und signed erschienen.
Insgesamt wurden 32 Pakete über 96 Versionen getroffen, Pakete mit
rund 117.000 wöchentlichen Downloads, und die breitere Kampagne
berührte 309 GitHub-Repositories. Sockets Einschätzung war, dass dies
„effektiv eine Mini-Shai-Hulud-Kampagne ist: sie nutzt dieselben
Kerntaktiken — Ausführung zur Installationszeit, Credential-Ernte,
CI/CD-Targeting, verschlüsselte Exfiltration und potenzielle
Downstream-Propagation." Red Hats Stellungnahme war, dass „die Pakete
streng auf interne Entwicklung beschränkt sind und der bösartige Code
nie zur Nutzung durch Kunden veröffentlicht wurde" — was wahr ist, und
auch nicht viel Trost für die Entwickler und CI-Runner, die
@redhat-cloud-services/* als transitive Abhängigkeit in dem Zeitfenster
zogen, bevor die Pakete zurückgezogen wurden.
Die Verteidigung, die jeder empfiehlt, ist die, die brach.
Wir schrieben über einen ähnlichen Wurm
vor drei Wochen — die
TanStack-Kompromittierung, bei der das verräterische Zeichen ein
prepare-Script war, das an einer gepinnten Git-URL hing, und eine
Bun-Laufzeit, die aus dem Nichts auftauchte. Die ehrliche Lehre aus
jenem Beitrag war: vertraue nicht der Lockfile, vertraue nicht der
Signatur. Miasma ist die nächste Drehung derselben Schraube, und es lohnt
sich, präzise zu sein, was anders ist, denn der Unterschied ist der ganze
Punkt.
Der Standard-Supply-Chain-Hygiene-Stack hat drei Sprossen. Pinne deine
Versionen. Verifiziere die Provenienz. Bevorzuge seriöse Publisher.
Miasma marschiert geradewegs durch alle drei. Pinning bewirkt nichts,
denn die bösartigen Versionen sind die veröffentlichten Versionen.
Provenienz bewirkt nichts, denn die Provenienz ist gültig — der
OIDC-Trusted-Publish-Flow war echt Red Hats CI, und downstream prägte der
Wurm Workflow-Commits, die GitHub selbst als verified und signed
markierte. Und die dritte Sprosse, bevorzuge seriöse Publisher, ist
hier nicht nur besiegt — sie ist die Angriffsfläche. Die Reputation des
@redhat-cloud-services-Scopes ist der Grund, warum die Pakete ohne
zweiten Blick gezogen werden. Je vertrauenswürdiger der Namespace, desto
nützlicher ist er für denjenigen, der ihn übernimmt.
Es gibt keine Variante von „lies das Paket sorgfältiger", die das erwischt. Das Paket ist in Ordnung. Das Paket ist Red Hats. Das Problem ist, dass Code-Ausführung zur Installationszeit mit den Ambient- Credentials des Entwicklers der Vertrag ist, und ein vertrauenswürdiger Name nichts daran ändert, was dieser Code anfassen kann, sobald er läuft.
Dieselbe Installation innerhalb von Bromure Agentic Coding.
Bromure Agentic Coding lässt Ihren Coding-Agent
innerhalb einer Linux-VM pro Profil laufen — eigener Kernel, eigenes
Dateisystem, eigener Netzwerk-Stack, auf Apples Virtualization-Framework.
Ein Profil ist ein kohärenter Arbeits-Scope: dieser Kunde, dieses
interne Produkt, diese Open-Source-Bibliothek. Der Agent erledigt sein
npm install-en dort drin, und der Host — Ihre echte Keychain, Ihre
echten Cloud-Credentials, Ihre echten SSH-Schlüssel — liegt auf der
anderen Seite einer hardware-erzwungenen Grenze, die der preinstall-Hook
nicht überqueren kann.
Die Credentials leben nicht im Profil. Sie leben auf dem Host, hinter
einem Credential-Broker. Wenn der
Agent einen Commit pushen oder ein Paket veröffentlichen muss, liest er
kein Token vom Gast-Dateisystem — es gibt keines zu lesen. Er bittet den
Broker, über einen Unix-Domain-Socket, ein Credential in seinem Namen zu
verwenden. Der Broker hält den echten Private Key der GitHub App, prägt
ein kurzlebiges Installation-Token, gescopt auf das Repo, an dem der Agent
ohnehin bereits arbeitete, und — für ein Profil, das so konfiguriert ist,
dass es das verlangt — blendet einen Autorisierungs-Prompt ein, den der
Entwickler auf dem Host beantwortet, bevor die Anfrage hinausgeht. Das
Token wird vollständig auf der Host-Seite geprägt und an die ausgehende
Anfrage angehängt; es betritt nie den Speicher oder die Disk des Gasts.
Das Prinzip, das so alt ist wie ssh-agent: vermittle die Verwendung
des Credentials, niemals seinen Wert.
Also gehen Sie Miasmas Durchsuchung durch diese Grenze. node index.js
liest ~/.aws/credentials und findet einen Stub oder nichts. Es liest
~/.npmrc und findet kein Publish-Token. Es liest die Umgebung nach
$GITHUB_TOKEN und findet nichts zu stehlen — das Installation-Token wird
auf dem Host geprägt und verbraucht, nie in den Gast geschrieben, und der
Broker prägt überhaupt nur eines, wenn der Entwickler den
Autorisierungs-Prompt beantwortet. Der GPG-Keyring, der private
SSH-Schlüssel, das Vault-Token, die kubeconfig: host-seitig, vermittelt,
falls überhaupt exponiert, abwesend, falls nicht. Die 4,2-MB-Nutzlast
läuft bis zum Ende durch, genau wie konstruiert. Sie exfiltriert nur einen
Gast, der nie die Schlüssel des Entwicklers hielt.
Der Push, den der Proxy weiterzuleiten verweigert.
Den Schlüssel zu stehlen ist nur die Hälfte von Miasma. Die andere Hälfte ist Propagation: er nutzte gestohlenen GitHub-Zugang, um vergiftete Workflows über die API zurückzucommitten, und das ist es, was eine schlechte Installation in 309 Repositories verwandelte. Der Broker behandelt den Diebstahl. Guardrails, hinzugefügt in Bromure Agentic Coding 2.0, behandeln den Missbrauch.
Guardrails sind eine host-seitige Policy-Engine, die innerhalb desselben
MITM-Proxys lebt, durch den der vermittelte Traffic ohnehin schon fließt,
sodass ein kompromittierter Agent im Gast nicht um sie herum routen kann.
Jede Anfrage wird danach klassifiziert, was sie tatsächlich mit der
Ressource tut, und jede Ressource — GitHub, AWS, Kubernetes,
Docker-Registries, DigitalOcean, GitLab, Bitbucket, gehostete Datenbanken —
kann auf aus, destruktive blockieren oder read-only gesetzt werden.
Setzen Sie das GitHub-Guardrail eines Profils in den read-only-Modus, und
ein git push — das git-receive-pack, das der Wurm braucht, um seinen
Workflow zurückzuschreiben — gibt ein hartes 403 zurück, während
git fetch weiter funktioniert. Ein DELETE gegen die Kubernetes-API,
eine Manifest-Löschung in einer Registry, ein Terminate*-Aufruf an EC2:
dieselbe Behandlung. Der Agent sieht einfach einen normalen API-Fehler.
Miasmas Propagationsschritt ist ein Write, den der Proxy abzulehnen
weiterzuleiten verweigert, ob der Agent je in die Nähe eines echten
Credentials kam oder nicht.
Was ist mit der Persistenz?
Hier ist das Modell pro Profil ehrlich über einen Preis. Miasma ist ein Wurm; sein ganzer Ehrgeiz ist es, zurückzukommen. In einer Wegwerf-Disk-Fantasie wischt man das weg — die Disk ist nach der Aufgabe weg. Ein Bromure-Profil ist langlebig, also kann eine Nutzlast, die sich selbst in ein Startup-Script innerhalb des Profils schreibt, in die nächste Agent-Session in diesem Profil überleben. Wir werden nicht so tun, als wäre es anders.
Was diese Persistenz allerdings erbt, ist ein Gast ohne Host-Schlüssel und ein Broker, der nur in kurzlebigen, scope-limitierten Tokens spricht. Der Wurm wacht in derselben Sandbox auf, in der er starb. Er kann dieselben Stubs lesen. Er kann den Broker bitten, ein Credential für das eine Repo zu verwenden, für das dieses Profil autorisiert ist — und der Entwickler muss immer noch den Autorisierungs-Prompt beantworten, damit das irgendwohin führt, wobei Guardrails frei sind, den Push rundheraus zu verweigern. Er kann die Host-Keychain, die anderen Profile oder die Cloud-Credentials des Entwicklers nicht erreichen, denn die waren von Anfang an nie innerhalb der Grenze. Persistenz kauft fortgesetzte Präsenz in einer Box, in der nichts drin ist.
Und jedes bisschen davon — das preinstall, das feuert, node index.js,
das einen mehrere Megabyte großen Blob lädt, die Datei, die in einen
Startup-Pfad geschrieben wird, der Egress-Versuch — landet im
Session-Trace auf Hypervisor-Ebene.
Wenn Aikido am nächsten Morgen die Indikatoren veröffentlicht, ist die
Frage „hat dieses Profil je Miasma ausgeführt?" ein grep, kein
Incident-Response-Einsatz.
Wo dich das nicht rettet.
Der Broker-Scope ist das ganze Spiel.
Wenn ein Profil heute bereitgestellt ist, um in deinen npm-Scope zu veröffentlichen, und dieses Profil heute Miasma installiert, wird der Broker es veröffentlichen lassen. Brokering funktioniert, weil der Grant schmal und kurzlebig ist. Ein Profil, das nicht veröffentlichen muss, sollte es nicht können. Scope es mit Absicht.
Es begutachtet das Diff nicht.
Miasma propagierte, indem es Workflows committete, die verified und signed erschienen. Ein read-only GitHub-Guardrail blockiert den Push rundheraus — aber ein Profil, das legitim pushen muss, läuft im destruktive-blockieren-Modus, und Guardrails klassifizieren nach Methode, nicht danach, was im Diff steht. Weder Isolation noch ein Guardrail auf Methodenebene hält einen Agent davon ab, dazu überredet zu werden, einen vergifteten Workflow zu committen, den er pushen darf. Lies das Diff. Der Trace sagt dir, welche Diffs zu lesen sind.
Die Zwischenablage ist standardmäßig geteilt.
Bromure wird mit aktiviertem Host/Gast-Zwischenablage-Sharing geliefert, weil das Einfügen eines Stack-Traces in einen Chat etwas ist, was Menschen den ganzen Tag tun. Für ein sensibles Profil isolieren Sie die Zwischenablage. Die Kontrolle existiert; sie ist nur nicht der Standard.
Der Trace ist ein Audit-Log, kein IDS.
Der Session-Trace zeichnet das preinstall, den Blob, den Egress auf. Er entscheidet nicht von sich aus, dass das Ziel feindlich ist. Er erfasst genug, dass, sobald jemand den Indikator benennt, deine Antwort zwei Sekunden entfernt ist.
Der nächste Scope ist bereits vertrauenswürdig.
Die Lehre des TanStack-Wurms war, dass die Lockfile und die Signatur
keine Verteidigungen sind. Miasma fügt das unbequeme Korollar hinzu: der
Publisher auch nicht. Der @redhat-cloud-services-Scope tat nichts
falsch, indem er vertrauenswürdig war — vertrauenswürdig zu sein ist der
ganze Zweck eines Anbieter-Namespace, und es ist genau das, was ihn des
Angriffs würdig machte. Die nächste Kampagne wird auf einem Scope
hereinreiten, dem du genauso sehr vertraust, genauso gültig signiert, von
einer Pipeline, die echt des Anbieters war, bis sie es nicht mehr war.
Das kannst du nicht beheben, indem du sorgfältiger vertraust. Du behebst
es, indem du die Dinge so arrangierst, dass „welcher Scope hat das
veröffentlicht" aufhört, die Frage zu sein, von der deine Keychain
abhängt. Bromure Agentic Coding ist die Konfiguration,
in der der Agent sein Installieren innerhalb einer VM pro Profil erledigt,
die echten Credentials auf dem Host hinter einem Broker bleiben, und das
Schlimmste, was ein preinstall-Hook anrichten kann, ist, eine Box zu
exfiltrieren, die nie deine Schlüssel hielt. Es ist kostenlos, Open Source
und heute ausgeliefert.