OVHcloud CLI Backdoored for 94 Minutes, Secrets at Risk
On Monday 19 October, someone with access to a contributor's GitHub account quietly swapped the download archives on five OVHcloud CLI releases. The replacement binaries were designed to steal secrets from any machine that ran them. OVHcloud caught it, killed the files, and shipped a clean replacement the same evening. But for 94 minutes, from 12:47 to 14:21 UTC, anyone who installed or updated the tool through certain paths got the bad build.
The affected releases are v0.11.0 through v0.15.0, published between April and September this year. On each, the attacker replaced the macOS, Linux x86_64 and arm64, and Windows x86_64 archives, along with the checksums file, so the published hashes matched the new binaries. The Linux i386, Windows i386, Windows arm64, and WebAssembly builds were left alone.
Who Actually Got It
Three paths exposed users: running the official install script (the curl-pipe-sh variety, which has never verified a hash), downloading directly from a GitHub release page, or running the CLI's own upgrade command on macOS or Linux from a v0.12.0-v0.14.0 install. That last one also skips hash verification.
Homebrew users were not affected. The cask in place during the window had the original SHA-256 pinned, and Homebrew would have simply refused to install anything that didn't match. Some early reports incorrectly named Homebrew as an exposed path; a check of the tap's commit history shows it didn't change until the clean v0.16.0 cask dropped on Monday evening.
Neither `go install` nor building from source was touched. The v0.15.0 tag still points at its original September commit. The Docker image was last pushed on 21 September, well before the swap, and hadn't been rebuilt.
Spotting the Bad Binary
A user noticed the swap after running `go version -m` on the v0.15.0 Linux arm64 binary and filed a public GitHub issue. Three details give it away.
The module version string reads `v0.15.1-0.20261013083505-5ead8ef9b43d+dirty`, which is Go's pseudo-version format for a build from an untagged commit, in this case one from October 13. Legitimate releases carry their tag number directly.
The embedded commit is `5ead8ef`, not `760fd72`, which is what the v0.15.0 tag actually points to.
The build flags include `-ldflags="-s -w"`. OVHcloud's real release pipeline uses a version flag that causes Go to omit the `-ldflags` line entirely from the recorded metadata. Its presence is a tell.
One caveat: advice floating around claiming that any `+dirty` build or any binary with vcs lines is malicious is too broad. The clean v0.16.0 binary also shows `+dirty` and `vcs.modified=true`. The combination of wrong commit, pseudo-version string, and the stripping flags is what marks the bad one.
The only published hash for a swapped archive is the v0.15.0 Linux arm64 file: `3833daffcaaaab27e4e0e0833240ffcb1df8df648f4ec0bc4a75c176e28933cb` (SHA-256). The original is `5c2beb56e6d83a4b426565a1557791ef759316abcc4effb38dd627c90aeb80e0`.
What to Do
If you installed or updated the OVHcloud CLI between 12:47 and 14:21 UTC on Monday via the install script, the GitHub release page, or the built-in upgrade command on macOS or Linux, assume you got the backdoored build.
OVHcloud founder Octave Klaba was blunt: rotate every secret on the affected machine. The CLI stores OVHcloud API credentials in `~/.ovh.conf` and reads from environment variables, but the advice extends to everything else readable from that disk. Rotation should happen from a different machine.
Delete the binary and install v0.16.0, which was published as an immutable release with a signed attestation. You can verify a downloaded archive with `gh release verify-asset v0.16.0 FILE`. Note that swapping in the new binary doesn't undo anything; rotation comes first.
OVHcloud hasn't disclosed which files the malware reads, where it exfiltrates data, or how many downloads occurred during the window. No copy of the swapped archive has been publicly analysed. A postmortem is promised.
How It Happened
GitHub, by default, lets anyone with write access to a repository delete and re-upload release assets. The download URLs don't change. GitHub introduced an immutability option for releases in October 2025 that locks files and tags, but it only protects releases created after you enable it.
OVHcloud hadn't enabled it. Klaba confirmed as much in a post on Monday night, noting that the setting's absence meant a user with the right permissions could modify existing releases directly without triggering anything in the company's CI/CD pipeline. The pipelines themselves were clean throughout. The attacker worked through a contributor account that had sufficient repository access, and whose owner has merged work in OVHcloud's documentation repository. The release workflow never fired during the attack window.
The swap was caught not by OVHcloud's own tooling, but by a customer whose CI job pins the SHA-256 of the Linux arm64 archive and started failing. With no private security reporting channel on the repository, they filed a public issue at 13:50 UTC. OVHcloud pulled the swapped files about thirty minutes later, and v0.16.0 shipped at 17:16 UTC, signed and immutable.
The GlassWorm Thread
Researchers at OpenSourceMalware link the compromised contributor account to GlassWorm, a malware campaign that hides loader code in invisible Unicode characters and pulls its next stage from the memo field of Solana wallet transactions. Four of the account's personal repositories were force-pushed in early March with an amended commit containing exactly this kind of loader, and the Solana wallet it references matches the one used in GlassWorm's ForceMemo campaign, which seeded malware into hundreds of Python repositories in March using stolen GitHub tokens.
The researchers are careful to note that the GlassWorm attribution is an inference. The shared account is the connecting thread. Nothing in the October binary has been tied to GlassWorm directly, partly because no copy of the swapped archive was preserved before OVHcloud deleted it.