OVHcloud CLI Releases Hijacked to Ship a Secret-Stealing Build
For roughly an hour and a half on Monday, October 19, anyone who installed or updated the OVHcloud command-line tool from GitHub may have received a malicious binary instead of the real one. An attacker who controlled a contributor's GitHub account swapped the download archives on five older releases for a build designed to harvest secrets from the machine it runs on. The source code, the release tags and OVHcloud's build pipeline were not touched. Only the files attached to the releases were.
What happened
Between 12:47 and 14:21 UTC, the archives attached to releases v0.11.0 through v0.15.0 of the ovhcloud-cli project were replaced. The affected platforms were macOS (x86_64 and arm64), Linux (x86_64 and arm64) and Windows (x86_64). The attacker also replaced each release's checksums.txt, so the published hashes matched the malicious files. That defeats any check that trusts the checksum file shipped next to the binary.
The rogue build appears to have been compiled from a later, untagged commit and uploaded by hand. It never went through OVHcloud's release workflow. The Linux i386, Windows i386, Windows arm64 and WebAssembly builds were left alone, and v0.10.0 is listed as clean.
The swap was caught by a customer whose CI job pinned the SHA-256 of the Linux arm64 archive and suddenly started failing. The customer opened a public GitHub issue, OVHcloud removed the swapped files about half an hour later, and a clean v0.16.0 shipped that evening as an immutable release with a signed tag and a release attestation.
Were you exposed?
You may have received a swapped file if, during the window and on one of the affected platforms, you:
- ran the official
curl … | shinstall script, which downloads the latest archive without checking a hash; - downloaded an archive manually from the release page of v0.11.0–v0.15.0;
- ran a CI job or build step that fetches the archive from GitHub without a pinned hash;
- ran the CLI's built-in upgrade command from v0.12.0–v0.14.0 on a macOS or Linux machine where the tool had been installed by script or by hand.
You were not exposed if you installed through Homebrew (the cask pins the original SHA-256 and would have refused the swapped file), used go install or built from source, pulled the Docker image (last pushed in September), or installed before 12:47 UTC and did not update during the window.
How to recognise the bad build
Without executing it, run go version -m against the binary. The swapped build shows:
- a pseudo-version module line:
v0.15.1-0.20261013083505-5ead8ef9b43d+dirty; - recorded commit
5ead8efinstead of760fd72, which is the commit the v0.15.0 tag points to; - an
-ldflags="-s -w"line, which genuine OVHcloud releases do not show.
Note that +dirty or vcs.modified=true on its own is not a sign of compromise. The clean v0.16.0 build reports both.
The only published hash for a swapped file covers the v0.15.0 Linux arm64 archive:
- Malicious:
3833daffcaaaab27e4e0e0833240ffcb1df8df648f4ec0bc4a75c176e28933cb - Original:
5c2beb56e6d83a4b426565a1557791ef759316abcc4effb38dd627c90aeb80e0
Don't run a suspect binary just to see what version it reports.
Why it matters
This wasn't a compromised build server or poisoned source code. It was the release asset layer. On GitHub, anyone with write access can delete and re-upload a release's files under the same names, and the download URL stays the same, unless release immutability is turned on. That feature has been generally available since October 2025, but it only protects releases created after it is enabled. It was not enabled on this repository. OVHcloud has since switched it on.
The incident also shows how fragile curl | sh and unpinned CI downloads are. The one control that worked was a customer's hash pin.
There are still important unknowns. OVHcloud has not said what the malicious binary reads, where it sends data, or how many copies were downloaded. No swapped archive has been analysed publicly, and a detailed postmortem has been promised. Researchers at OpenSourceMalware have linked the hijacked account to the GlassWorm campaign, which hides code in invisible Unicode characters and pulls its next stage from Solana transaction memos. However, they describe that link as their own inference. Nothing from the October binary itself has been tied to GlassWorm, so treat the attribution as unconfirmed.
What to do
- Rotate first. If a machine ran a swapped build, or you can't rule it out, treat every secret readable on that machine as exposed. That includes OVHcloud API keys in
~/.ovh.confand environment variables, but also cloud tokens, SSH keys, Git credentials and anything else on disk. Do the rotation from a different, clean machine. - Replace the binary with v0.16.0. Upgrading does not revoke a key that was already copied, which is why rotation comes first.
- Verify downloads against the release attestation:
gh release verify-asset v0.16.0 <FILE>. - Pin hashes in CI. Fetch third-party binaries by a known SHA-256 that you store yourself, not one taken from a checksum file next to the download.
- Enable release immutability on your own GitHub repositories and review who holds write access, including outside contributors.
Unpinned downloads, curl | sh installers and CI steps that trust whatever a URL returns are easy to miss in a large codebase. Our AI-assisted code review flags these patterns in pipelines and build scripts, so a single swapped artifact can't quietly reach your developers' machines.
Credit: this story was originally reported by The Hacker News. This is our own summary and analysis.
