Eine generierte abstrakte Illustration auf dunkelblauem Grund: ein Stapel aus fünf dünnen cyanfarbenen Speicherträgern im Schnitt, die jeweils Reihen kleiner grauer Blöcke enthalten, wobei ein kleiner bernsteinfarbener Würfel zwischen dem dritten und vierten Träger eingeschoben ist; von diesem Würfel zieht sich ein dünner bernsteinfarbener Partikelfaden in einem Bogen nach rechts über einen dunklen Leerraum hinweg zu drei kleinen rot-orangen Knoten, die in einem Dreieck angeordnet sind. Hinter den Trägern hängen matte graue Anhänger an dünnen Ringen von einem Schlüsselring. Es erscheinen keine Texte, Personen oder Organisationslogos. Das OrcaRouter-Logo ist in die untere rechte Ecke eingefügt.
AI Safety Incidents

sckit: Die KI-Speicherpakete von MemTensor wurden mit Backdoors versehen, um Agenten-Anmeldedaten und Prompts zu stehlen

Autor

Rowan Sterling

Veröffentlicht am

Neueste Modelle · 20Alle Modelle ansehen →
Benchmarks: Artificial Analysis · täglich aktualisiert
Zurück zu allen Beiträgen

Vier MemTensor-Releases, veröffentlicht am 23. September 2026, trugen dasselbe abgespeckte Go-Implantat, und jedes davon war die neueste Version in seiner Registry, solange es live war. Das npm-Paket @memtensor/memos-cloud-openclaw-plugin wurde als 0.1.21 um 02:23 UTC, 0.1.23 um 03:49 und 0.1.25 um 04:36; das PyPI-Paket MemoryOS wurde als 2.0.34 um 05:25 veröffentlicht. Alle vier lieferten sckit mit, das startet, wenn das OpenClaw-Agent-Gateway bootet, bei jedem Memory-Recall erneut startet — wobei der Prompt-Text des Nutzers in einer Umgebungsvariable übergeben wird — und im Python-Paket bei einem einfachen Import des memos-Moduls startet. Anschließend durchsucht es das Home-Verzeichnis nach npm-, PyPI-, GitHub-, GitLab-, AWS-, Vault- und SSH-Secrets und sendet die Funde an Server unter skyleen[.]fr. Socket, StepSecurity, SafeDep und Aikido dokumentierten die Kompromittierung am selben Tag unabhängig voneinander, und keines von ihnen meldete Hinweise darauf, dass das Implantat auf einem echten Host gelaufen war. Das Orca AI Incident Archive enthält diesen Eintrag vollständig, zusammen mit jedem anderen Supply-Chain-Vorfall, den es protokolliert hat, und jeder Datensatz trägt seine eigene Konfidenzstufe und seinen eigenen Schadensstatus.

Vier Releases – und mittendrin ein öffentlicher Bugreport.

MemOS ist MemTensors quelloffenes Speicherframework für LLM-Agenten, und das npm-Paket ist der Konnektor, der es einer OpenClaw-Agent-Runtime ermöglicht, lesend und schreibend auf einen gehosteten Speicherdienst zuzugreifen; StepSecurity weist darauf hin, dass dasselbe Paket außerdem Integrationspunkte für die Clawdbot- und Moltbot-Runtimes deklariert. Socket bezifferte das Repository auf etwa 11.500 Stars und 1.100 Forks zum Zeitpunkt der Veröffentlichung. Diese Position ist der Grund dafür, dass die Kompromittierung vier separate Untersuchungen auslöste: Wie StepSecurity es ausdrückte, „platziert dies das Plugin in einem Prozess, der routinemäßig Benutzereingaben verarbeitet und möglicherweise wertvolle Zugangsdaten erbt.“ Betroffen sind diejenigen, die eines der beiden Pakete installiert haben – Entwickler auf ihren eigenen Rechnern sowie CI-Runner und Container, die lediglich eine Testsuite ausgeführt haben.

Die npm-Sequenz ist der klarste Teil des Datensatzes, weil die Registry-Zeitstempel öffentlich sind und mehrere Firmen sie unabhängig erfasst haben. Der Bericht von Socket und die Zeitleiste von SafeDep stimmen auf die Minute genau überein: 0.1.21 um 02:23:04, 0.1.22 um 03:45:44, 0.1.23 um 03:49:20, 0.1.24 um 04:33:30 und 0.1.25 um 04:36:58. Die Versionen 0.1.22 und 0.1.24 waren sauber — Socket sagt, sie entsprachen 0.1.20 mit Ausnahme der Versionszeichenfolgen — und die Payload kehrte dreieinhalb Minuten nach jeder dieser Versionen zurück.

Der Sprung bei der Dateigröße ist der entscheidende Hinweis. Socket maß 0.1.20 mit etwa 272 KB ungepackt und 0.1.21 mit 43,6 MB, weil die bösartigen Releases sechs statisch gelinkte Plattform-Binärdateien von jeweils rund 7,4 MB enthielten. PyPI zeigt dasselbe Muster: Das 2.0.34-Wheel war 19.201.772 Bytes groß gegenüber 951.210 für 2.0.33, so Socket.

Um 04:17 UTC — sechzehn Minuten vor der sauberen 0.1.24 und neunzehn Minuten, bevor die Payload als 0.1.25 zurückkam — eröffnete ein GitHub-Nutzer namens omeridel Issue #173 im Plugin-Repository mit dem Titel „Bösartige Versionen 0.1.21 und 0.1.23 auf npm veröffentlicht — Publish-Token offenbar kompromittiert“. Im Issue wird angemerkt, dass 0.1.23 damals das neueste Tag war, dass keine der beiden Versionen mit einem Commit oder Tag im Repository übereinstimmte und dass der letzte legitime Commit vom 14. August datierte. Stand 26. Oktober 2026 ist es weiterhin offen, ohne Kommentare der Maintainer.

A self-built HTML card headed 'Supply chain, 23 September 2026, all times UTC', titled 'Four and a half hours on npm and PyPI', subtitled 'Each malicious release was the registry's newest version while it was live'. Nine rows, each with a time, an event, a detail and a status chip: 00:48 attacker branch first pushed, pipeline; 02:23 npm 0.1.21 published, 43.6 MB unpacked up from 272 KB, malicious; 03:17 MemOS commit b52958f, six sckit binaries and a CI token stealer, malicious; 03:45 npm 0.1.22 published, matches 0.1.20 apart from version strings, clean; 03:49 npm 0.1.23 published, payload restored three minutes later, malicious; 04:17 GitHub issue 173 filed, disclosure; 04:33 npm 0.1.24 published, clean again and the latest tag for three minutes; 04:36 npm 0.1.25 published, payload back and this one takes the latest tag, malicious; 05:25 PyPI MemoryOS 2.0.34, 19.2 MB wheel against 951 KB in 2.0.33, malicious. A footer reads 'Timestamps from Socket and SafeDep, which agree to the minute. Sizes from Socket.' The OrcaRouter logo is composited in the bottom-right corner.

Was sckit tut, sobald das Paket geladen ist

Keines der beiden Pakete verwendete einen Install-Hook, weshalb der übliche Rat zu --ignore-scripts nicht griff. Die Analyse der npm-Variante durch StepSecurity beschreibt eine neue Datei, lib/sckit.js, die einen Launcher exportiert, den der vorhandene Start- und Memory-Recall-Code des Plugins importiert und aufruft. Beim Start lädt sie einen abgekoppelten .sckit/<os>-<arch>/sckit-Prozess mit stage0 --config64 und der vollständigen Umgebung des übergeordneten Prozesses; beim Recall verfährt sie genauso und übergibt den bereinigten Benutzer-Prompt über eine Umgebungsvariable namens SCKIT_EVENT_TEXT. Socket brachte die Konsequenz auf den Punkt: Die Binärdatei läuft daher bei jedem Recall erneut.

Die PyPI-Variante ist kürzer und in der Praxis schwerer zu vermeiden. Socket fand heraus, dass memos/log.py eine Triggerfunktion innerhalb von memos/_stage0.py aufruft, wenn die Protokollierung konfiguriert ist, dass 149 Module den Logger auf Modulebene aufrufen und dass daher ein einfacher Import des memos-Moduls ausreicht, um die Payload einmal pro Prozess zu starten. Die Analyse desselben Pakets durch StepSecurity war rein statisch – sie hat es weder installiert noch importiert, gebaut oder ausgeführt.

Der Erfassungsumfang ist das gesamte Home-Verzeichnis. SafeDep listet das Inventarstammverzeichnis als $HOME und die Zieldateien als .npmrc, .pypirc, .git-credentials, .netrc, id_rsa, id_ecdsa, id_ed25519, .vault-token, msal_token_cache, access_tokens.json und access_tokens.db, plus Umgebungsvariablen, deren Namen Token, Secret, Passwort, API-Schlüssel oder Datenbank-URL enthalten, plus erkannte Tokenformate für GitHub, GitLab, npm, PyPI, Hugging Face, Slack, Stripe, AWS und SendGrid. Die OSV-Datensätze für die beiden Pakete, MAL-2026-16476 für npm und MAL-2026-16475 für PyPI, beschreiben dieselbe Dateiliste und fügen hinzu, dass das Command-and-Control-Protokoll CBOR, X25519-Schlüsselaustausch und XChaCha20-Poly1305 verwendet, mit signierten Leases und Modulen, die zur Laufzeit geliefert werden — daher wurden die Inhalte der Module nie beobachtet, nur der Loader, der sie abruft.

Zwei Details bestimmen, was ein Verteidiger noch wiederherstellen kann. Die Binärdatei enthält Selbstlöschroutinen namens scheduleSelfDelete und deleteExecutable, laut dem OSV-Eintrag, weshalb die Empfehlung lautet, nach Prozess- und Netzwerkartefakten statt nach Dateien zu suchen. Und 0.1.25 ergänzte lib/tls-trust.js, was SSL_CERT_FILE auf minimalen Linux-Systemen auf eine mitgelieferte Datei mit 145 Zertifizierungsstellen setzt, laut StepSecurity — eine Korrektur, die darauf abzielt, dass der eigene Datenverkehr in Containern funktioniert, denen ein System-Trust-Store fehlt.

A generated abstract illustration on a dark navy field: at left, a dim cyan isometric tree of folders, several leaves carrying small grey key and badge silhouettes; from those keys a cluster of amber threads lifts away, braids into one bright cord and runs right through a narrow vertical cyan gateway frame that carries an amber keyhole, toward three small red-orange receivers with faint pulse rings on the far right. No text, people or organisation logos appear. The OrcaRouter logo is composited in the bottom-right corner.

Die Release-Pipeline war der Weg hinein.

00:48 und 02:03 UTCwurde von einem GitHub-Konto, das als Memtensor-AI fungierte, fünf Mal ein Branch namens sc/release-0.1.21-20260922-cloud erstellt, gepusht und gelöscht. Commit 9b97ec6 änderte das Workflow-Skript .github/scripts/validate-release-confirmation.mjs so, dass es einen BASH_ENV-Wert an $GITHUB_ENV anhängte, wodurch spätere nicht-interaktive Shell-Schritte eine vom Angreifer bereitgestellte sckit-publish-bridge.sh einlasen, bevor sie ihre eigenen Befehle ausführten. Diese Bridge prüfte den Paketnamen und das 150-Sekunden-Zeitlimit des Publish-Schritts, rief den Token-Collector mit NPM_TOKEN oder NODE_AUTH_TOKEN auf, löschte sich selbst und beendete sich mit Exit-Code 1 — sodass die Veröffentlichung fehlschlug, nachdem das Token abgegriffen worden war. Die erste bösartige npm-Version erschien zwanzig Minuten nach dem letzten Branch-Push.

Der PyPI-Weg nutzte denselben Trick gegen eine andere Pipeline. SafeDep berichtet, dass Tag v2.0.34 auf nicht signierte Commits zeigte, die nicht auf main waren, und dass Commit b52958f, verfasst als "MemTensor CI Review", die sechs Binärdateien, einen Python-Loader und ein benutzerdefiniertes Build-Backend namens sckit_poetry_build hinzufügte. Dieses Backend schrieb ein BASH_ENV mit Verweis auf _pypi_bridge.sh in $GITHUB_ENV; die Bridge agierte nur innerhalb des twine-Upload-Wrappers, holte einen signierten Index vom Host skyleen[.]fr, verifizierte einen Emitter mit einer Ed25519-Implementierung, gab eine Markerzeile aus, entfernte das Upload-Passwort und beendete sich, ohne etwas hochzuladen. Etwa zwei Stunden später entfernte Commit 41bf5c7 diesen Aufruf mit der Meldung "chore: allow native PyPI upload [skip ci]", das Tag wurde innerhalb von zehn Sekunden gelöscht und neu erstellt, und der PyPI-Upload folgte 62 Sekunden danach. SafeDep liest den ersten Commit als einen Token-Capture-Lauf und den zweiten als den Lauf, der MemTensors eigenen Workflow das bösartige Paket mit dem echten Token des Projekts bauen und veröffentlichen ließ.

Nicht alle Darstellungen stimmen hierin überein. Socket beobachtete, dass die npm-Releases vom selben npm-Konto wie frühere legitime Versionen stammten und keinen gitHead enthielten, was es als Hinweis darauf deutete, dass sie nicht von der CI des Projekts erzeugt wurden, und erklärte, es könne nicht bestätigen, wie der Angreifer Veröffentlichungszugriff erlangte. SC Media, die am 24. September über Sockets Erkenntnisse berichteten, zog denselben Schluss in Richtung einer Kontokompromittierung. Die beiden Darstellungen stimmen darin überein, dass Veröffentlichungsanmeldedaten aus der Release-Pipeline entwendet wurden, und unterscheiden sich darin, wie das npm-Artefakt selbst erzeugt wurde; niemand hat die Workflow-Logs veröffentlicht, weil die GitHub Actions API nach dem 7. September keine Läufe anzeigte und SafeDep daraus schließt, dass die Datensätze gelöscht wurden. Wie das Memtensor-AI-Konto überhaupt Push-Zugriff erlangte, ist in beiden Darstellungen unbekannt; SafeDep hält ein gestohlenes Konto-Token für wahrscheinlich, aber nicht bestätigt.

Etabliert, abgeleitet und nicht vorhanden

Die Vertrauensstufe des Eintrags ist A, und er ist nicht umstritten – was eine präzise Formulierung verdient, denn die Gewissheit bezieht sich auf das, was veröffentlicht wurde, und nicht auf das, was er bewirkte.

• Festgestellt: den Inhalt der vier Artefakte, rekonstruiert durch statische Analyse bei Socket, StepSecurity und SafeDep; die npm-Veröffentlichungszeiten und das Latest-Tag auf 0.1.25; den Größensprung in beiden Ökosystemen; die Commits, Tags und die Branch-Historie in den beiden Repositories; die Infrastruktur skyleen[.]fr und die Kampagnen-IDs cloud-openclaw-semi-nuclear und memos-semi-nuclear; sowie die Konfiguration der Payload, die laut Socket und SafeDep am 22.–23. Oktober 2026 abläuft.

• Gefolgert: dass das Tool mit Hilfe eines Sprachmodells geschrieben wurde, was SafeDep direkt sagt und als Schlussfolgerung bezeichnet; und dass die gestohlenen Publish-Tokens wiederverwendet werden sollten, was die Kanalzeichenfolge der Konfiguration – „exact-ref-one-use-NPM_TOKEN“ – stützt, aber nicht beweist.

• Nicht geklärt: wer der Angreifer war; ob jemals eine Kopie von sckit außerhalb einer Sandbox ausgeführt wurde; ob irgendeine Anmeldeinformation einen Host verlassen hat; ob irgendein in einen OpenClaw-Agenten eingegebener Prompt den Angreifer erreicht hat; und ob irgendein nachgelagertes Paket erneut veröffentlicht wurde. Socket und StepSecurity arbeiteten beide statisch, und StepSecurity gibt an, dass in seiner Analyse kein Prozesslauf, keine Übertragung von Geheimnissen, keine erfolgreiche Exfiltration, keine Workflow-Installation und keine weitere Paketveröffentlichung beobachtet wurde.

Diese Lücke ist der Grund, warum das Archiv diesen Vorfall mit dem Vermerk „real harm" = falsch führt. Die Exposition ist real und breit gefächert – jedem, der eine betroffene Version installiert hat, wird geraten, den Host als kompromittiert zu behandeln –, doch ein Schaden im Sinne einer nachweislich verwendeten Zugangsberechtigung oder eines nachweislich erreichten Systems wurde von keiner der vier ermittelnden Firmen verzeichnet.

A self-built HTML card headed 'What the record supports', titled 'Four investigating firms, no confirmed victim', subtitled 'Socket, StepSecurity, SafeDep and Aikido documented the same four artefacts on 23 September 2026'. The left column, headed 'Established by static analysis', lists: four malicious releases, npm 0.1.21, 0.1.23 and 0.1.25 and PyPI MemoryOS 2.0.34; one implant, the same stripped Go binary sckit in all four; the publish window 02:23 to 05:25 UTC with 0.1.25 tagged latest; package growth from 272 KB to 43.6 MB on npm and 951 KB to 19.2 MB for the PyPI wheel; six builds per package for Linux, macOS and Windows on amd64 and arm64; collection scoped to the whole home directory across registry, source-control, cloud, Vault and SSH secrets; exfiltration to servers under skyleen[.]fr; and OSV tracking as MAL-2026-16476 and MAL-2026-16475. The right column, headed 'Not established', lists: the attacker's identity; how Memtensor-AI obtained push access; whether any copy ever executed outside static analysis; whether a stolen secret reached the attacker; whether any prompt text was received; and whether any downstream package was republished. A footer reads 'Archive classification for this record: incident, severity high, confidence A, real harm false.' The OrcaRouter logo is composited in the bottom-right corner.

Der Wurm, der nie beim Ausbreiten beobachtet wurde

Die Binärdateien enthalten mehr als einen Stealer. SafeDep listet Funktionen namens recursivePublish, prepareRemoteNode, prepareRemotePython und prepareRemoteWorkflow auf, außerdem eine eingebettete GitHub-Actions-Vorlage, die bei Push ausgelöst wird, und die Möglichkeit, eine Workflow-Datei namens runtime-update.yml in Repositories zu schreiben, die das Implantat erreichen kann. Socket fand Zeichenfolgen zur Codierung von Paketmanifesten und zur Installation von Repository-Dateien und kam zu der Einschätzung, dass die Binärdateien möglicherweise Pakete mithilfe gestohlener Registry-Token erneut veröffentlichen können.

Das ist ein Wurmdesign. Es ist kein Wurm, dessen Funktionieren beobachtet wurde. StepSecurity fand keine Hinweise darauf, dass die Logik jemals zur Verbreitung genutzt wurde, und die Forschungsnotiz der Cloud Security Alliance vom 25. September bewertet die Fähigkeit als begrenztes Selbstverbreitungspotenzial statt als bestätigtes Wurmverhalten. Mehrere Medien beschrieben den Fall als den ersten Supply-Chain-Wurm, der auf die Gedächtnisinfrastruktur von KI-Agenten abzielt; die Beschreibung ist als Aussage über das Design angemessen, und die Berichte stützen sie nicht als Aussage darüber, was tatsächlich geschah.

Was hat sich danach geändert?

Die Registries wurden noch am selben Tag bereinigt. Bei einer Prüfung am 26. Oktober 2026 sind in den npm-Paketmetadaten {{1}}0.1.21{{/1}}, {{2}}0.1.23{{/2}} oder {{3}}0.1.25{{/3}} nicht mehr unter den Versionen aufgeführt, das Latest-Tag verweist auf {{4}}0.1.24{{/4}}, und das Paket wurde zuletzt am 23. September um 11:53 UTC geändert. Zwei ungewöhnliche Dist-Tags sind noch angehängt – {{5}}clean-inverse-0-1-23{{/5}} zeigt auf {{6}}0.1.22{{/6}} und {{7}}clean-inverse-0-1-25{{/7}} zeigt auf {{8}}0.1.24{{/8}} – und spiegeln die beiden sauberen Releases wider, die die bösartigen kurz unterbrochen haben. Auf PyPI ist MemoryOS {{9}}2.0.34{{/9}} verschwunden, und die neueste Version ist {{10}}2.0.33{{/10}}, hochgeladen am 3. September 2026; seitdem gab es in den sieben Wochen keine weitere PyPI-Version.

Was sich nicht geändert hat, ist die öffentliche Außendarstellung des Projekts. Das Repository listet keine Sicherheitshinweise auf, das GitHub-Issue von 04:17 am Tag des Vorfalls ist weiterhin offen und unbeantwortet, und keiner der hier untersuchten Berichte zitiert eine Stellungnahme von MemTensor oder von OpenClaw. Keines der beiden bösartigen Pakete trug eine Provenienzattestierung, was laut SafeDep das eine Signal dafür beseitigte, dass die Artefakte aus einem unerwarteten Commit gebaut worden waren.

Die Reaktion, die es gibt, liegt auf der Erkennungsseite: StepSecurity hat die Command-and-Control-Domains skyleen[.]fr zur globalen Blocklist hinzugefügt, und die beiden Pakete werden in OSV als MAL-2026-16476 und MAL-2026-16475 geführt.

Wenn eine betroffene Version installiert wurde

Die Empfehlung von Socket ist die strengste und die einfachste: Wenn eine der aufgeführten Versionen geladen oder importiert wurde, behandeln Sie diesen Host als kompromittiert – einschließlich CI-Runner und Container, die nur Tests ausgeführt haben. Die konkreten Schritte, auf die sich die vier Unternehmen verständigen:

• Entfernen Sie das Paket und pinnen Sie es an eine saubere Version — npm 0.1.20, PyPI 2.0.33. StepSecurity warnt, dass seine Analyse keine saubere PyPI-Basislinie ermitteln konnte, während SafeDep und SC Media beide 2.0.33 als das letzte gute Release nennen.

• Suchen Sie nach der Prozessbefehlszeile, da sich die ausführbare Datei selbst löschen kann: sckit stage0 --config64, und nach der Umgebungsvariable SCKIT_EVENT_TEXT.

• Löschen Sie die Statusverzeichnisse ~/.openclaw/.cache/runtime und ~/.memos/.cache/runtime, und prüfen Sie die Repositories auf unerwartete runtime-update.yml-Workflows oder .sckit/-Verzeichnisse.

• Rotieren Sie alle Anmeldedaten, die vom Home-Verzeichnis und der Prozessumgebung aus erreichbar sind, von einem sauberen Rechner aus: npm, PyPI, GitHub, GitLab, AWS, Vault, SSH, Hugging Face, Slack, Stripe und SendGrid sowie alle .env-Werte. Registry- und Quellcodeverwaltungs-Tokens kommen zuerst.

• Prüfe die Releases deiner eigenen Pakete – für den Fall, dass ein gestohlenes Publish-Token verwendet wurde, um Versionen zu veröffentlichen, die nicht von dir stammen.

• skyleen[.]fr und seine Subdomains blockieren und Egress-Logs bis zum 23. September zurücklesen.

• Behandle jeden Prompt und jedes eingefügte Geheimnis, das während seiner Aktivierung durch das Plugin lief, als offengelegt. Dies ist der Teil des Vorfalls, der spezifisch für das Agentengedächtnis ist: Das Implantat musste kein Transkript auslesen, weil ihm das Transkript bei jedem Recall übergeben wurde.