Analyse von Angriffen auf die Rust-Lieferkette und das Problem mit „build.rs“

Die „php2shell“-Patches (CVE-2026-109618 und CVE-2026-109619) für PHP am Ende des Lebenszyklus (EOL) sind nun verfügbar. Da die Antworten des Vertriebs aufgrund der hohen Nachfrage derzeit langsamer als gewöhnlich ausfallen, ist der schnellste Weg zu den gepatchten Paketen der Online-Kauf von ELS für Runtimes (wird in einem neuen Tab geöffnet). Lesen Sie die FAQ zu den Patches

Gehen Sie direkt zu einer KI-Zusammenfassung dieses Blogbeitrags

  • Fasse diesen Beitrag mit Perplexity zusammen
  • Fasse diesen Beitrag mit Gemini zusammen

Wichtigste Erkenntnisse

  • Ein bösartiger build.rs Das Skript wird ausgeführt, während cargo build mit den Berechtigungen des jeweiligen Prozesses, der Cargo aufgerufen hat.
  • Stable Cargo bietet keine unterstützte Möglichkeit, einen Abhängigkeitsbaum zu erstellen, und lässt gleichzeitig die Ausführung seiner Build-Skripte nicht zu.
  • Sechs der 34 schädlichen Pakete von TrapDoor landeten auf crates.io, gegenüber 21 auf npm und 7 auf PyPI.
  • npm und pnpm blockieren nun standardmäßig nicht genehmigte Skripte zur Installation von Abhängigkeiten, und die stabile Version von Cargo verfügt über keine entsprechende Funktion für alle Abhängigkeiten.

Die Rust-Entwickler hören schon seit Jahren, dass die Sprache sicher sei. Speichersicherheit, keine Datenkonflikte in sicherem Code, ein Typsystem, das bereits zur Kompilierungszeit Fehler aufspürt, über die andere Sprachen erst zur Laufzeit stolpern. Nichts davon betrifft Code, der ausgeführt wird, bevor Ihr Programm überhaupt existiert. Im Mai 2026 startete eine Kampagne zur Software-Lieferkette namens TrapDoor 34 bösartige Pakete in mehr als 384 Versionen auf npm, PyPI und crates.io veröffentlicht. Keines davon wartete darauf, dass Sie das Paket aufriefen. Sie wurden bei der Installation, beim Import oder während der Kompilierung ausgelöst. Sechs der 34 befanden sich auf crates.io, getarnt als Sui- und Move-Tools, und nutzten build.rs um nach Keystores für Krypto-Wallets zu suchen. Ein Crate-Autor kann sein eigenes Build-Skript im Manifest deaktivieren. Als Nutzer steht Ihnen jedoch kein allgemeiner Schalter zur Verfügung, mit dem Sie die Build-Skripte der Abhängigkeiten im gesamten Baum deaktivieren können. Um diese Lücke geht es in diesem Artikel.

Was TrapDoor in drei Registern geleistet hat

npm, PyPI und crates.io waren nicht gleichermaßen betroffen. Von den 34 identifizierten Paketen befanden sich 21 auf npm und nutzten Postinstall-Skripte, um eine gemeinsame Payload zum Abgreifen von Anmeldedaten auszuführen, sobald jemand ein Paket installierte. Sieben befanden sich auf PyPI und wurden beim Import ausgeführt, um eine entfernte JavaScript-Payload abzurufen und lokal auszuführen. Nur sechs landeten auf crates.io und nutzten Rust-Build-Skripte, die während der Kompilierung ausgeführt wurden. Dieses Muster ist das verbindende Element der Kampagne. In jedem Ökosystem griff der Angreifer auf den Ausführungshaken zurück, den ihm das jeweilige Ökosystem bereits zur Verfügung stellte.

Registrierung Benannte Pakete Ausführungs-Hook Was es bewirkt hat
npm 21 Skripte für den Lebenszyklus nach der Installation Ran trap-core.js, ein Tool zum Sammeln gemeinsam genutzter Anmeldedaten mit SSH-basierter lateraler Bewegung
PyPI 7 Ausführung zum Zeitpunkt des Imports Eine Remote-JS-Payload wurde über node -e
crates.io 6 build.rs Build-Skripte Nach Keystores der Wallets „Sui“ und „Aptos“ gesucht, diese XOR-verschlüsselt und auf GitHub Gists hochgeladen

Die sechs crates.io-Pakete – move-analyzer-build, move-compiler-tools, move-project-builder, sui-framework-helpers, sui-move-build-helperund sui-sdk-build-utils – richteten sich eher speziell an Sui- und Move-Entwickler als an die allgemeine Rust-Community. Auf der npm-Seite war der Schaden hinsichtlich der Anzahl der Pakete und der Komplexität der Payloads am größten. Die crates.io-Seite ist für Rust-Entwickler nach wie vor am wichtigsten, da sie eine build.rs Skript, das genau das tut, was ein build.rs Das Skript ist dafür vorgesehen. Es läuft im Hintergrund mit den Berechtigungen des Build-Prozesses, noch bevor die Anwendung selbst überhaupt gestartet wird.

Warum „build.rs“ eine bessere Wahl ist als ein Skript nach der Installation

Ausführungs-Hooks über npm, PyPI und crates.io hinweg im Rahmen des „TrapDoor“-Angriffs auf die Rust-Lieferkette
Sowohl npm als auch pnpm blockieren nun standardmäßig nicht genehmigte Installationsskripte für Abhängigkeiten, wobei es eine Zulassungsliste gibt, die Sie für die Pakete, die diese Skripte tatsächlich benötigen, genehmigen und festschreiben. pnpm tut dies bereits seit Version 10 im Januar 2025. npm hat dies erst mit Version 12 im Juli 2026 umgesetzt – Wochen nach „TrapDoor“ –, sodass diese Postinstall-Payloads für alle, die während der Kampagne eine Installation durchführten, weiterhin standardmäßig ausgeführt wurden. Stable Cargo verfügt über keine entsprechende, für alle Abhängigkeiten geltende Whitelist oder standardmäßige Sperre. build.rs ist ein Rust-Programm, das Cargo vor der Kompilierung der Crate, zu der es gehört, kompiliert und ausführt – und zwar mit den Berechtigungen des Prozesses, in dem Cargo läuft. Es gibt gute Gründe dafür, wie beispielsweise die Codegenerierung und die native Verknüpfung, und viele legitime Crates enthalten ein solches Programm. Jede Abhängigkeit, deren Build-Skript ausgeführt wird, kann beliebigen Code mit den Berechtigungen ausführen, die dem Cargo-Prozess zur Verfügung stehen. „TrapDoor“ ist die Bezeichnung dafür, wenn jemand dies absichtlich ausnutzt. Die sechs Crates, deren Namen so gewählt wurden, dass sie wie die Build-Tools von Sui und Move aussehen, nutzten build.rs um einen Rechner nach Wallet-Keystores zu durchsuchen, sobald jemand das Programm gestartet hat cargo build. Das Skript verschlüsselte alles, was es fand, mit XOR und übermittelte es an GitHub Gists. Kein separater Installations-Hook, kein Import – lediglich das Kompilieren eines Projekts, das zufällig von einem von sechs Paketnamen abhängig war. Prozedurale Makros sind der andere Ausführungsweg zur Kompilierungszeit in Rust, und TrapDoor benötigte diese nicht. Ein proc-Makro wird während der Makroauswertung im Compiler ausgeführt, was bedeutet, dass es nur dann ausgelöst wird, wenn es tatsächlich aufgerufen wird. Ein Build-Skript wird ausgelöst, weil sich die Crate überhaupt im Build-Graphen befindet – und genau das macht es für einen Angreifer zur zuverlässigeren Option.

Mechanismus Läuft während Allgemeine Steuerung des Paketmanagers
npm-Lebenszyklus-Skript Installieren Ja, seit npm 12 standardmäßig blockiert
Ausführung zur Importzeit in Python Paketimport Nein
Rost build.rs Zusammenstellung Nein
Prozedurales Makro in Rust Makro-Erweiterung Nein

Cargo bietet keinen stabilen, universell einsetzbaren Schalter, mit dem ein Nutzer einen Abhängigkeitsbaum erstellen kann, während er gleichzeitig die Ausführung von Abhängigkeits-Build-Skripten oder die Makroauswertung unterbindet. Es gibt eine einzige, eng gefasste Ausnahme. Wenn ein Crate ein links Mit dem Schlüssel können Sie das Build-Skript in der Cargo-Konfiguration überschreiben, indem Sie die Metadaten selbst angeben; dieses Skript wird dann niemals kompiliert oder ausgeführt. Dies gilt für Shims für native Bibliotheken, nicht für eine beliebige Abhängigkeit, für die ein Build-Skript mitgeliefert wird. cargo build --offline verhindert, dass Cargo Netzwerkanfragen stellt, und eine festgeschriebene Cargo.lock Versionen festlegen, aber weder verhindert dies die Ausführung eines bereits in Ihrem Baum vorhandenen Build-Skripts, noch hilft es, wenn die in Ihrer Sperrdatei festgelegte Version die schädliche ist.

Wo ein Build-Skript ausgeführt wird und worauf es Zugriff hat

Zugriffsrechte, auf die eine bösartige „build.rs“-Datei auf einem CI-Runner im Vergleich zu einem Entwickler-Laptop zugreifen kann
Ein CI-Runner, der cargo build Enthält in der Regel Anmeldedaten für Cloud-Rollen, Registry-Token, Zugriffsrechte auf Container-Registerstellen und manchmal auch Signaturschlüssel. Auf dem Laptop eines Entwicklers befinden sich meist all diese Daten sowie SSH-Schlüssel, Browsersitzungsdaten und Quellcode für noch nicht veröffentlichte Projekte. Genau das macht einen Build-Host überhaupt erst zu einem lohnenden Angriffsziel. Sakshi Grover, Senior Research Manager bei IDC Asia Pacific Cybersecurity Services, sagte gegenüber CSO Online Nachdem TrapDoor bekannt wurde, dass „ein einziger kompromittierter Arbeitsplatzrechner unbemerkt zu einem Einstiegspunkt in CI/CD-Pipelines werden kann“. Ein Build-Skript, das Anmeldedaten sammelt, ist eine Möglichkeit dafür, und das Abrufen von Wallet-Keystores direkt aus dem Dateisystem während eines unbeaufsichtigten Builds war genau das, was die crates.io-Seite von TrapDoor tat.

Der Abschnitt über KI-Codierungsassistenten

Wie TrapDoor die von KI-Programmierassistenten gelesenen CLAUDE.md- und .cursorrules-Dateien manipuliert hat
Die Manipulation von KI-Assistenten-Dateien durch TrapDoor war kein build.rs Trick. Er stammte aus dem Einbetten von Payloads in npm. .cursorrules und CLAUDE.md Dateien als Persistenz, mit den schädlichen Anweisungen verborgen hinter einem Unicode-Zeichen mit der Breite Null, sowie derselbe Angreifer GitHub-Pull-Anfragen eröffnen gegen unabhängige KI- und Entwickler-Tooling-Projekte. Beide Dateinamen sind Konventionen, die KI-Codierungstools lesen, um eine Codebasis zu verstehen; ein manipulierter Dateiname stellt daher eine indirekte Prompt-Injektion dar. Der Text des Angreifers landet in einer Datei, die der Assistent als Anleitung statt als Daten behandelt. Die Voraussetzung ist jedoch enger gefasst als „jedes KI-Tool ist kompromittiert“. Ob die Technik zum Erfolg führt, hängt davon ab, welche Anweisungsdateien ein bestimmter Assistent entdeckt, als vertrauenswürdig einstuft und befolgt. Es lohnt sich auf jeden Fall, dies zu tun. Suchen Sie nach Anweisungsdateien des Assistenten an allen Orten außerhalb des Stammverzeichnisses Ihres Repositorys und behandeln Sie einen Treffer innerhalb einer Vendor- oder Pfadabhängigkeit standardmäßig als verdächtig. Dies funktioniert als CI-Prüfung, solange Sie den Exit-Code umkehren, sodass das Auffinden eines solchen Elements den Build tatsächlich zum Scheitern bringt, anstatt ihn zu bestehen.

if find . -name 'CLAUDE.md' -o -name '.cursorrules' \
  | grep -vE '^\./(CLAUDE\.md|\.cursorrules)$' | grep -q .; then
  echo "Unexpected AI assistant instruction file found"
  exit 1
fi

Das ist ein anderes Ziel als die Täuschung eines menschlichen Prüfers. Das Manipulieren einer Datei zum Zeitpunkt der Persistenz bedeutet, dass der Nutzen erst später zum Tragen kommt – nämlich dann, wenn ein Assistent das Projekt das nächste Mal liest und die Datei als legitime Anweisung behandelt. Die Lösung liegt vor allem im Umfang. Durch die Einschränkung der Anweisungsdateien, denen ein Assistent vertraut, wird die Angriffsfläche verkleinert, insbesondere wenn abhängigkeitsgesteuerte Pfade ausgeschlossen werden.

Was beim Herausreißen einer Kiste tatsächlich entfernt wird

Das crates.io-Registry verfolgt einen ungewöhnlichen Ansatz, der sich größtenteils als vorteilhaft erweist. Veröffentlichte Versionen sind unveränderlich und können nicht gelöscht, sondern lediglich zurückgezogen werden. Dadurch wird eine ganze Klasse von Angriffen verhindert, unter denen veränderliche Registries leiden. Das bedeutet auch, dass ein Zurückziehen eine weniger wirksame Abhilfemaßnahme ist, als die meisten Menschen annehmen.

Aktion Wirkung
Eine Version herunterladen Neue Auflösungen überspringen es, bestehende Sperrdateien verwenden es weiterhin
Alle Versionen entfernen Der Name der Crate bleibt unverändert, der Code bleibt zum Herunterladen verfügbar
Eine Version löschen Auf crates.io nicht möglich

Eine bereits in einem Commit gespeicherte, zurückgezogene Version Cargo.lock bleibt im Einsatz. Das ist beabsichtigt, damit die Builds nicht von selbst fehlschlagen, bedeutet aber auch, dass eine Organisation, die eine schädliche Version fixiert hat, weiterhin damit baut, bis jemand die Sperrdatei tatsächlich bearbeitet. Führen Sie cargo update --dry-run um zu sehen, was sich ändern würde, und führen Sie dann den entsprechenden Befehl aus cargo update um die Sperrdatei neu zu schreiben, sobald Sie sich vergewissert haben, dass die Ersatzversionen unbedenklich sind.

Warum das mit Rust so oder so passieren musste

Angreifer folgen der Verbreitung. Angesichts der wachsenden Bedeutung von Rust in den Bereichen Infrastruktur, Kryptografie und Systemsoftware in den letzten Jahren war es nur eine Frage der Zeit – nicht des Ob. Crates, die vor einigen Jahren noch kleine Nebenprojekte waren, sind mittlerweile fest in Produktionsstacks integriert. Build-Skripte sind in der Rust-Community gang und gäbe, während dies bei Postinstall-Skripten in npm nicht der Fall ist. Ein Paket mit einem Postinstall-Skript wird von Prüfern mit besonderer Aufmerksamkeit betrachtet. build.rs ist nicht der Fall, da Crates, die Code generieren, Plattformfunktionen prüfen oder native Bibliotheken verknüpfen, alle einen berechtigten Grund haben, einen solchen mitzuliefern. Diese berechtigte Verwendung ist es, die das bloße Vorhandensein von build.rs ein so schwaches Signal. Das ist keineswegs TrapDoor crates.io’s erste Begegnung mit Malware. Bereits im Jahr 2023 hat die Registrierungsstelle neun durch Typosquatting erlangte Crates entfernt, deren build.rs Die Dateien haben die Metadaten des Hosts an einen Telegram-Kanal gesendet, und Angriffe auf die Lieferkette Auf crates.io sind seitdem so viele neu hinzugekommen, dass das Team im Februar 2026 aufgehört hat, über jede einzelne davon zu bloggen. Das Neue an TrapDoor ist, dass crates.io im Rahmen einer koordinierten Kampagne auftaucht, die npm und PyPI in derselben Welle erfasst hat. Diese beiden hatten bereits Jahre zuvor ihre eigene Version davon durchgemacht, und zwar in viel größerem Umfang, als ihre Paketanzahlen Typosquatting sowie ähnlich klingende Namen, die für einen Angreifer lohnenswert sind. TrapDoor bindet crates.io in dasselbe ökosystemübergreifende Bedrohungsmodell ein, das Sicherheitsteams bereits für npm und PyPI anwenden.

Sicherung der Rust-Lieferkette

SecureChain für Rust überprüft eine Crate, bevor sie in Ihren Abhängigkeitsbaum aufgenommen wird, und durchsucht den Quellcode nach Angriffsmustern zur Erstellungszeit, einschließlich bösartiger build.rs Skripte und prozedurale Makros sowie das Blockieren derjenigen, die fehlschlagen. Crates werden aus verifizierter Quelle neu kompiliert, anstatt direkt aus dem öffentlichen Register übernommen zu werden. Das ist die Art von Kontrollinstanz, die vor einem Paket wie sui-framework-helpers, denn sobald ein feindlicher build.rs befindet sich im Baum und wird ausgeführt cargo build ist bereits zu spät. Außerdem werden damit weiterhin Sicherheitslücken in Crates behoben, die sich bereits in Ihrem Stack befinden, einschließlich derer, deren Betreuer sich nicht mehr melden. TrapDoor ist das unmittelbare Problem. Das meiste, was letztendlich in einen Rust-Produktionsbaum gelangt, ist die langsamere Variante, und es lohnt sich, auch diese abzudecken. Abonnieren Sie den TuxCare-Newsletter für eine ähnliche Analyse, wenn eine Kampagne das nächste Mal einen neuen Paketnamen und ein neues Ökosystem wählt, in dem sie sich verstecken kann.

FAQ

Was ist ein Rust-Supply-Chain-Angriff?

Ein Angriff, bei dem Code oder Abhängigkeiten kompromittiert werden, bevor sie Sie erreichen – meist durch bösartige oder manipulierte Crates auf crates.io. In Rust sind Build-Skripte und prozedurale Makros die beiden wichtigsten Ausführungswege zur Kompilierungszeit, da beide Code ausführen, bevor die resultierende Anwendung gestartet wird.

Was ist „build.rs“ und warum ist es gefährlich?

build.rs ist ein Rust-Programm, das Cargo vor dem Erstellen der Crate, zu der es gehört, kompiliert und ausführt – und zwar mit den Berechtigungen des Prozesses, in dem Cargo läuft. Es dient der legitimen Codegenerierung und der nativen Verknüpfung; jede Abhängigkeit, die ein solches Programm enthält, kann beliebigen Code mit den Berechtigungen ausführen, über die der Cargo-Build-Prozess verfügt.

Brauchte TrapDoor tatsächlich „build.rs“, oder hätte jeder beliebige Rust-Build-Hook funktioniert?

build.rs Das reichte aus und war der geringste Aufwand, also wurde genau das bei den sechs Crates so gehandhabt. Ein prozedurales Makro ist der andere Weg zur Kompilierungszeit, aber es wird nur ausgeführt, wenn der aufrufende Code das Makro tatsächlich aufruft, während ein Build-Skript einfach deshalb ausgeführt wird, weil sich das Crate im Build-Graphen befindet. Die Angreifer wählten build.rs weil es ihnen den entscheidenden Ansatzpunkt lieferte, den sie brauchten.

Wird eine Kiste aus crates.io entfernt, wenn man sie herauszieht?

Nein. Durch das „Yanking“ wird verhindert, dass neue Resolutionen diese Version auswählen, während sie weiterhin zum Herunterladen verfügbar bleibt, und eine bereits in einer bestehenden Resolution festgelegte Version Cargo.lock wird immer wieder verwendet. Das Löschen einer veröffentlichten Version ist auf crates.io nicht möglich.

Was waren die manipulierten KI-Assistenten-Dateien in „TrapDoor“?

Die .cursorrules und CLAUDE.md In den Dateien wurden Unicode-Zeichen mit der Breite Null verwendet, um Anweisungen für KI-Programmierassistenten zu verbergen. Im Rahmen der Kampagne wurde zudem versucht, ähnliche Dateien über GitHub-Pull-Requests in nicht damit in Zusammenhang stehende Projekte einzuschleusen.

Zusammenfassung
Analyse von Angriffen auf die Rust-Lieferkette und das Problem mit „build.rs“
Artikel Name
Analyse von Angriffen auf die Rust-Lieferkette und das Problem mit „build.rs“
Beschreibung
TrapDoor hat in sechs Crates bösartige „build.rs“-Skripte versteckt, die während der Kompilierung Wallet-Schlüssel gestohlen haben, und Cargo kann diese nach wie vor nicht blockieren.
Autor
Name des Herausgebers
TuxCare
Logo des Herausgebers

Schließen Sie sich 4.500+ Linux- und Open-Source-Experten an!

2x im Monat. Kein Spam.

Inhaltsübersicht
Holen Sie sich die Open-Source-Sicherheitslösungen, die Sie brauchen

Schließen Sie sich 4.500+ Linux- und Open-Source-Experten an!

2x im Monat. Kein Spam.