Betroffen sind ausschließlich Nutzer, die in diesem Zeitfenster das OVHcloud-CLI über einen Pfad ohne Hash-Prüfung installiert oder aktualisiert haben – auf macOS, Linux x86_64 oder arm64 sowie Windows x86_64. OVHcloud löschte die ausgetauschten Archive und veröffentlichte noch am Abend eine saubere Version v0.16.0 als unveränderliches Release, dessen Dateien GitHub nicht mehr verändern lässt. Quellcode, Release-Tag und die Build-Pipeline des Unternehmens blieben unangetastet: Der schädliche Build war ein schlichtes “go build” eines späteren Commits, das direkt auf Releases hochgeladen wurde, die zwischen April und September erschienen waren.

Bei v0.15.0 ersetzte der Angreifer sechs Dateien: die macOS-Archive für x86_64 und arm64, die Linux-Archive für x86_64 und arm64, das Windows-Archiv für x86_64 sowie die Datei checksums.txt – so passten die veröffentlichten Prüfsummen zu den neuen Binaries. Dieselben sechs Dateien fehlen inzwischen auch in v0.11.0 bis v0.14.0. Die Builds für Linux i386, Windows i386, Windows arm64 und WebAssembly blieben in allen Releases unberührt. OVHcloud führt v0.11.0 bis v0.15.0 als kompromittiert, v0.10.0 als sauber. Diese fünf Releases erschienen zwischen dem 14. April und dem 16. September; eine Kopie, die vor 12:47 UTC am Montag installiert und seither nicht aktualisiert wurde, ist das Original.

Eine manipulierte Datei erhielt, wer im fraglichen Zeitfenster auf einer der genannten Plattformen:

  • das offizielle Installationsskript ausführte (curl -fsSL …/install.sh | sh), das das neueste Release-Archiv lädt und installiert und noch nie einen Hash geprüft hat;
  • ein Archiv von der GitHub-Release-Seite einer der fünf Versionen herunterlud;
  • einen CI-Job oder Build-Schritt laufen ließ, der das Archiv ohne festgelegten Hash von der Release-Download-URL bezieht;
  • den eingebauten Upgrade-Befehl aus einer Installation von v0.12.0, v0.13.0 oder v0.14.0 auf einem macOS- oder Linux-System ausführte, auf dem das Werkzeug per Skript oder manuell installiert war. Der Befehl lädt das Archiv und ersetzt die Binärdatei ohne Hash-Prüfung; bei einer Installation über Homebrew oder “go install” gibt er stattdessen nur den auszuführenden Befehl aus.

Nicht betroffen sind Installationen über Homebrew: Das während des Zeitfensters gültige Cask legte die ursprüngliche SHA-256-Summe jedes Archivs fest, und Homebrew verweigert einen Download, dessen Hash nicht passt – “brew install” oder “brew upgrade” wären also fehlgeschlagen statt die manipulierte Datei zu installieren. Frühe Darstellungen führten Homebrew unter den gefährdeten Pfaden; die Commit-Historie des Taps zeigt jedoch, dass sich zwischen dem v0.15.0-Cask vom 16. September und dem v0.16.0-Cask vom Montagabend nichts geändert hat. Ebenfalls unbetroffen: “go install” und Builds aus dem Quellcode – das Tag v0.15.0 verweist weiterhin auf seinen September-Commit 760fd72 – sowie das Docker-Image, dessen “latest”-Tag zuletzt am 21. September veröffentlicht und bis Dienstag nicht neu gebaut wurde.

Aufgefallen ist der Austausch einem Kunden, dessen CI-Job die SHA-256-Summe des Linux-arm64-Archivs festschreibt und daraufhin fehlschlug. Da das Repository keinen privaten Meldekanal bot, eröffnete der Kunde laut der von OpenSourceMalware erstellten Zeitleiste um 13:50 UTC ein öffentliches Issue; rund eine halbe Stunde später, um 14:21 UTC (16:21 Uhr in Paris), löschte OVHcloud die ausgetauschten Dateien. v0.16.0 folgte um 17:16 UTC, veröffentlicht unter dem Unternehmenskonto ovh-cds mit signiertem Tag.

Derselbe Kunde zog mit “go version -m” die Build-Informationen aus der neuen v0.15.0-Binärdatei für Linux arm64 – der Befehl liest die Datei, ohne sie auszuführen – und veröffentlichte sie im Issue. Drei Merkmale kennzeichnen den schädlichen Build: Die Modulzeile lautet v0.15.1-0.20261013083505-5ead8ef9b43d+dirty, eine Pseudoversion, die Go für einen Build aus einem ungetaggten Commit erzeugt, hier vom 13. Oktober; ein echtes Release trägt seine Tag-Nummer, der saubere v0.16.0-Build von OVHcloud zeigt v0.16.0+dirty. Der aufgezeichnete Commit ist 5ead8ef statt 760fd72. Und es findet sich eine Zeile -ldflags="-s -w"; die Release-Pipeline von OVHcloud baut mit einem Versions-Flag, das Go nicht in die aufgezeichneten Flags übernimmt, sodass ein echtes Release gar keine -ldflags-Zeile zeigt.

Kursierende Hinweise, jeder Build mit der Markierung +dirty oder mit vcs-Zeilen sei der schädliche, würden auch das Original von OVHcloud treffen: Derselbe Befehl auf der sauberen v0.16.0-Binärdatei für Linux x86_64 meldet v0.16.0+dirty, vcs.modified=true und den Commit, aus dem sie gebaut wurde. Von den ausgetauschten Dateien ist bislang nur eine Prüfsumme veröffentlicht, die des Linux-arm64-Archivs von v0.15.0:

  • manipuliertes Archiv (SHA-256): 3833daffcaaaab27e4e0e0833240ffcb1df8df648f4ec0bc4a75c176e28933cb
  • Originalarchiv (SHA-256): 5c2beb56e6d83a4b426565a1557791ef759316abcc4effb38dd627c90aeb80e0

Ein Build ohne Versions-Flag würde seine Version als “undefined” ausgeben – eine verdächtige Binärdatei dafür auszuführen, ist allerdings nicht ratsam.

OVHcloud-Gründer Octave Klaba schrieb am Montagabend auf X, Betroffene sollten jedes auf der Festplatte gespeicherte Geheimnis ändern. Das CLI legt die OVHcloud-API-Zugangsdaten laut Dokumentation in ~/.ovh.conf ab und liest sie aus Umgebungsvariablen; der Rat gilt jedoch für alles auf der Platte, nicht nur für diese Dateien. Wer einen ausgetauschten Build ausgeführt hat oder es nicht sicher weiß, sollte jedes von dieser Maschine lesbare Geheimnis als offengelegt behandeln und rotieren – nach Empfehlung von OpenSourceMalware, das den Vorfall untersucht hat, von einem anderen Rechner aus. Anschließend ist die Binärdatei zu entfernen und v0.16.0 zu installieren; das Release ist unveränderlich und trägt eine signierte Release-Attestierung. Ein Update ersetzt lediglich das Programm, widerruft aber keinen bereits kopierten Schlüssel – deshalb kommt die Rotation zuerst. Heruntergeladene Archive lassen sich mit “gh release verify-asset v0.16.0 FILE” gegen das Release prüfen, wie GitHub dokumentiert.

Welche Dateien die Binärdatei liest, wohin sie diese sendet und wie viele Kopien heruntergeladen wurden, hat OVHcloud nicht mitgeteilt; eine Kopie eines ausgetauschten Archivs wurde öffentlich bislang nicht analysiert. Das Unternehmen hat eine ausführliche Nachbetrachtung in den kommenden Tagen zugesagt.

Möglich wurde der Austausch, weil jeder mit Schreibzugriff auf ein GitHub-Repository die an ein Release angehängten Dateien löschen und neue mit denselben Namen hochladen kann, ohne dass sich die Download-URL ändert – es sei denn, die Release-Unveränderlichkeit ist aktiviert. Diese seit Oktober 2025 allgemein verfügbare Einstellung sperrt Dateien und Tag eines Releases, schützt aber nur Releases, die nach ihrer Aktivierung angelegt wurden. OVHcloud hatte sie nicht eingeschaltet. In einem zweiten Beitrag in der Montagnacht schrieb Klaba, das Problem rühre daher, dass die Unveränderlichkeitsoption nicht aktiviert war, sodass ein Nutzer mit den entsprechenden Rechten bestehende Releases direkt auf GitHub ändern konnte, ohne dass die CI/CD-Pipeline des Unternehmens etwas prüfte. Die Option sei nun aktiviert, die Pipelines selbst seien nicht betroffen. Die fünf alten Releases bieten jetzt nur noch die vier Archive an, die der Angreifer nicht angefasst hat.

Die Uploads liefen nach Angaben von OpenSourceMalware, das eine Zeitleiste aus den serverseitigen Aufzeichnungen von GitHub erstellte, über das Konto eines Mitwirkenden, dessen zusammengeführte Arbeit im Dokumentations-Repository von OVHcloud liegt und der kein öffentliches Mitglied der Organisation ist. Der Release-Workflow lief nie: Die Lauf-Liste zeigt zwischen dem 16. Oktober und dem Push des v0.16.0-Tags um 16:00 UTC am Montag keinen Workflow. Erste Prüfungen hätten kein weiteres betroffenes Repository ergeben, schrieb Klaba in seinem ersten Beitrag; wie die Zugangsdaten des Kontos entwendet wurden, hat OVHcloud nicht mitgeteilt.

OpenSourceMalware bringt das Konto mit GlassWorm in Verbindung, jener Kampagne, die Code in unsichtbaren Unicode-Zeichen versteckt und ihre nächste Stufe aus dem Memo-Feld von Transaktionen einer Solana-Wallet nachlädt. Vier der persönlichen Repositories des Kontos wurden den Forschern zufolge am 5. und 6. März per Force-Push mit einem geänderten Commit versehen, der einen Loader dieser Art hinzufügte. Die Wallet, die dieser Loader ausliest, ist jene, die in GlassWorms ForceMemo-Kampagne genannt wird, bei der im März mit gestohlenen GitHub-Token Schadcode in hunderte Python-Repositories gepusht wurde. Die Loader-Datei liegt mit der von den Forschern veröffentlichten Prüfsumme weiterhin in einem dieser Repositories. Ob derselbe Akteur hinter beidem steckt, sei “unsere Schlussfolgerung”, schreiben die Forscher: Das gemeinsame Konto ist die Verbindung, und nichts aus der Oktober-Binärdatei konnte mit GlassWorm verknüpft werden, weil keine Kopie davon erhalten blieb.