- Affected: ovhcloud-cli v0.11.0 to v0.15.0 downloaded 12:47 to 14:21 UTC on 19 Oct 2026 (macOS, Linux, Windows x86_64 archives). v0.10.0 and v0.16.0 are listed as clean[1].
- Do not run the binary to check it. Hash it and compare against the five MD5 values in OVHcloud's advisory, or look for an envchecker- folder in your temp directory.
- If you are affected: rotate cloud, SSH, Git, Docker, Kubernetes and AI tooling credentials from a different machine, delete the binary, then install v0.16.0.
- Root cause: release immutability was off, so a privileged account could overwrite assets on old releases without touching CI[5].
- Maintainers: Settings, Releases, Enable release immutability. It only applies to future releases[8].
- Users: pin a hash in CI and run gh release verify-asset. A checksums file inside a mutable release proves nothing, because it was swapped too[6].
If you installed or updated the OVHcloud CLI (ovhcloud) between 12:47 and 14:21 UTC on 19 October 2026 and ended up on v0.11.0 through v0.15.0, treat every secret readable from that machine as stolen. An attacker used a hijacked developer account to replace the release archives, and OVHcloud's own advisory says the build was meant to harvest secrets from disk[1]. The fix for maintainers is one checkbox: GitHub immutable releases lock a published release's assets and tag[7]. Below: who is affected, what to do tonight, why mutable release assets made this possible, a table of defences, how to switch immutability on, and how to verify a CLI before you run it.
What happened on 19 October 2026
The advisory (GHSA-862f-55f5-vmvw, severity High, no CVE) says a compromised OVHcloud developer GitHub account was used to replace release binaries with malicious builds. Source code and the build chain were not affected, and no other repositories were touched[1]. The Hacker News adds a detail that matters for defenders: the bad build was a plain go build from a later commit, uploaded on top of existing releases, so the release workflow never ran during the window[5].
A downstream user caught it. Their CI pinned the SHA-256 of the Linux arm64 tarball, the pin started failing, and they opened issue #300 on the repository at about 13:50 UTC[2][6]. A maintainer replied that all binaries involved were deleted at 16:21 GMT+2 (14:21 UTC), and v0.16.0 followed as an immutable release with a signed tag[2][3].
Versions, platforms and the time window
| Item | Detail | Source |
|---|---|---|
| Affected releases | v0.11.0, v0.12.0, v0.13.0, v0.14.0, v0.15.0 | OVHcloud advisory[1] |
| Clean releases | v0.10.0 and earlier, v0.16.0 and later | OVHcloud advisory[1] |
| Affected platforms | Darwin arm64, Darwin x86_64, Linux arm64, Linux x86_64, Windows x86_64 | OVHcloud advisory[1] |
| Not replaced | Linux i386, Windows i386, Windows arm64, WASM build | OpenSourceMalware[6] |
| Exposure window | 12:47 to 14:21 UTC (14:47 to 16:21 UTC+2) on 19 Oct | OVHcloud advisory[1] |
Press coverage disagrees on timing, so here is how to read it. BleepingComputer reports the compromised release appearing at 14:47 and being blocked at 16:21 with no timezone stated[4]. Those are Paris times. The Hacker News gives 12:47 to 14:21 UTC[5]. OpenSourceMalware's 12:47 to about 13:12 is the span in which the five releases were overwritten, not how long the files stayed up[6]. The advisory's UTC window of 12:47 to 14:21 is the one to use. Anything downloaded from those five releases before 12:47 UTC is outside it, per the advisory.
How people actually got hit
According to The Hacker News, the exposed paths were the official install script (which does not check a hash), manual downloads from the five release pages, CI jobs fetching without a pinned hash, and the CLI's own upgrade command from v0.12.0 to v0.14.0 on macOS and Linux. The same report lists Homebrew (the cask pinned the original SHA-256), go install and source builds, and the Docker image as not exposed[5]. Sources disagree on Homebrew: OpenSourceMalware lists the cask as an exposed path[6], while The Hacker News says it checked the tap history and the pinned hash would have made brew refuse the swapped file. OVHcloud's advisory does not mention Homebrew. That split is the whole story of this post: every path that verified a hash held up, and every path that trusted the release URL did not.
Is it GlassWorm?
OpenSourceMalware links the compromised account to the GlassWorm malware family. The evidence: a Solana wallet in the account's earlier force-pushed repositories that appears in public GlassWorm indicator lists. The researchers themselves call the link to the October swap their inference, and no October binary has been tied to GlassWorm because no copy was preserved[6]. Treat the attribution as tentative. It does not change what you do.
What to do tonight if you may be affected
Work through this in order. Rotation comes before the upgrade, because installing v0.16.0 does nothing about keys that were already copied.
- Find the binary and hash it without running it. The advisory lists MD5 values for the malicious binaries: Darwin arm64
6f2f086239f3d88eb2750e871901927d, Darwin x86_64347e65eb7f2d78d1c6872690272a6cc3, Linux arm6401f57206d37c28cf711677f612052913, Linux x86_64301bff0b51980b9e76c93633e7cfd3bd, and Windows6a3cf153338c416169cda2fe704c8848[1]. - Look for the dropped folder. A directory named envchecker- followed by random digits in your temp directory means the malware ran[1].
- Rotate from a different machine. The advisory names cloud, SSH, Git, Docker, Kubernetes and AI assistant tooling credentials[1]. OpenSourceMalware's list adds package-manager tokens and
.envfiles[6]. OVHcloud's CEO told affected users to change every secret on disk, per BleepingComputer[4]. - Delete the binary, then install v0.16.0.
- Check CI. Any pipeline that downloaded the CLI in the window without a pinned hash ran the swapped build on a runner that holds deploy credentials.
Hashing a binary is the easy part. Knowing what was on disk is the hard part. If you need an inventory, the AI Provider Key Hygiene Kit scans files and git history for AI provider keys and ships a rotation runbook. The same rotate-what-was-on-disk logic applied in the OpenCode console breach checklist, and the order of operations is identical: revoke first, investigate second.
Why it worked: release assets were mutable
A GitHub release is a page with files attached. Unless the repository opts in to immutability, anyone with write access can delete an attached file and upload a different one under the same name. The tag keeps pointing at the same commit, the source archive looks fine, and the release date does not change. OVHcloud's CEO said the cause was the immutability option being disabled, which let a sufficiently privileged account modify existing releases directly, bypassing the CI/CD checks, per BleepingComputer[4]. The advisory's own scope line fits: the pipelines were not the weak point[1].
OpenSourceMalware lists the contributing weaknesses beyond mutability: releases published under personal accounts, a peripheral contributor holding release-asset write permission, an install script that skips checksum verification, no provenance or signing before v0.16.0, and no private vulnerability reporting channel, so disclosure happened in a public issue[6]. The checksum file was no help either. The same report says checksums.txt was one of the six files replaced on each affected release[5][6]. A hash that lives next to the file it vouches for is only a typo check.
Defences compared: what each stops and who has to act
| Defence | What it stops | What it does not stop | Who acts |
|---|---|---|---|
| GitHub immutable releases | Replacing or deleting assets, and moving or deleting the tag, on a published release[7] | Releases published before it was switched on[8]. A compromised account cutting a brand-new release, which is a new, separately visible event | Maintainer |
| Release attestation (generated automatically for immutable releases) | Lets anyone confirm a local file matches an asset on the release[7] | Malicious code that was in the release when it was published | Maintainer publishes, user verifies |
| Checksums file inside the same release | Corrupted downloads | A swapped release, because the attacker replaces the checksums too[6] | Both, and low value |
| Checksum or signature published somewhere the uploader cannot edit | A swap by anyone who can only touch the release page | A compromised maintainer machine or signing key | Maintainer publishes, user checks |
| Hash pinned in your CI or install script | Any swap after you recorded the hash. This is what exposed the incident[2] | A release that was already bad when you pinned it | User |
| Package manager with pinned hashes (Homebrew cask) | Same swap, because the cask held the original SHA-256, per The Hacker News[5] | A maintainer who updates the pin to a bad file | Packager |
| Install script that downloads and runs with no hash check | Nothing | Everything above | Maintainer should fix; user should avoid |
Two rows deserve a sentence each. Immutability is not a malware filter: it freezes whatever you published, good or bad, and it cannot stop an attacker from publishing a new release under a new tag. What it removes is the quiet rewrite of a trusted old release, which is exactly what let a v0.11.0 download from April turn hostile in October. And the signed-checksums row is a general pattern, not something OVHcloud shipped. Where a signature key lives matters more than the format.
For maintainers: turn on immutable releases
GitHub's documentation gives the steps[8].
One repository
- Open the repository, then Settings (under the ⋯ menu if it is hidden).
- Scroll to the Releases section and select Enable release immutability.
A whole organization
- Open the organization, then Settings.
- In the sidebar, under Code, planning, and automation, open Repository and click General.
- In the Releases section, change the No policy dropdown to All repositories or Selected repositories.
- For Selected repositories, click the gear icon, pick the repositories, and click Select repositories.
Read the caveat before you celebrate: the docs say immutability applies only to future releases[8]. Enabling it today does not retroactively lock last year's releases. The docs say nothing more about releases published before the switch, so for anything you must stand behind, cut a fresh release and point people at it. That is what OVHcloud did with v0.16.0, which its release page labels as an immutable release where only the title and notes can be edited[3].
The docs also describe a publishing order that fits immutability: create the release as a draft, attach every asset, then publish, so nothing is missing at the moment it locks[7]. Creating an immutable release automatically generates a release attestation that records the tag, the commit SHA and the assets[7].
What else to change on the same afternoon
- Audit who holds write access on release-publishing repositories. In this incident the account was a contributor, not a core maintainer[6].
- Publish releases from a bot or organization-owned identity driven by your workflow, not from a person's account.
- Turn on private vulnerability reporting. OVHcloud enabled it after the incident[2], and the reporter here had to use a public issue.
- Make your install script check a hash, or delete it and point people to a package manager that pins one.
- Sign tags. The v0.16.0 tag is signed, though its page flags the signing key as expired[3]. A signature you cannot trust the key for is weaker than it looks, so keep keys current.
For users: verify a CLI before you run it
You have three checks, from cheapest to strongest. None requires running the download.
1. Hash it
On Linux, sha256sum ovhcloud-cli_Linux_arm64.tar.gz. On macOS, shasum -a 256 ovhcloud-cli_Linux_arm64.tar.gz. Compare against a value you got from somewhere other than the release page you downloaded from: the maintainer's docs, a package manager, or the value you recorded last time. If you only have a browser, the hash generator has a file mode that computes MD5, SHA-1, SHA-256 and SHA-512 for a file you drop in, which is handy for matching the advisory's MD5 list. For the incident here, OpenSourceMalware published SHA-256 values for the v0.15.0 Linux arm64 archive: the swapped file ended in ...28933cb and the original in ...b80e0[6].
2. Verify against the release itself
GitHub's documentation shows two commands for releases that are immutable[9]:
# confirm the release exists and is immutable
gh release verify v0.16.0 --repo ovh/ovhcloud-cli
# confirm a local file is an exact match for an asset on the release
gh release verify-asset v0.16.0 ./ovhcloud-cli_Linux_arm64.tar.gz --repo ovh/ovhcloud-cliRun them inside a clone of the repository, or add gh's repository flag. The first command answers whether the release can still change under you. The second answers whether your file is the one attached to it. The docs add that source zip and tarball downloads cannot be checked this way, because GitHub generates them on request[9]. In the web interface, an immutable release shows an Immutable label below its title[9]. OpenSourceMalware also recommends gh attestation verify for v0.16.0[6]. We ran gh attestation verify ovhcloud-cli_Linux_arm64.tar.gz --repo ovh/ovhcloud-cli on 20 October and got an HTTP 404: v0.16.0 has no build-provenance attestation, only the release attestation that GitHub creates for immutable releases. gh release verify-asset checks that one, and it passed on the same file. So use verify-asset for this CLI, and do not read a failed gh attestation verify as proof of tampering.
3. Pin it where an attacker cannot edit it
The reporter of issue #300 never ran a verify command. They had a SHA-256 in CI, and the build broke when the file changed[2]. Pin the hash in your repository, in a Dockerfile, in a bootstrap script. Update it by pull request, with a person reading the diff. A failing pin is the cheapest intrusion detector most teams will ever deploy.
Pipelines deserve extra attention because they hold the most valuable secrets and the least human supervision. If your CI downloads tools with curl and pipes to a shell, you have the exposure OVHcloud users had. The SecretsSafe CI/CD secrets audit pack is a checklist for finding which jobs hold which credentials, which tells you the blast radius before an incident does.
Frequently asked questions
Am I affected if I installed the CLI with Homebrew?
Sources disagree. The Hacker News reports the Homebrew cask pinned the original SHA-256 and was not exposed, along with go install, source builds and the Docker image[5]. OpenSourceMalware lists the cask as exposed[6], and the advisory does not mention Homebrew. The advisory's own scope is anyone who downloaded the five releases in the 12:47 to 14:21 UTC window[1]. If you cannot say which route your machine used, hash the binary.
Does updating to v0.16.0 fix it?
It replaces the binary. It does not revoke credentials that a malicious build already read. Rotate first, from a clean machine, then upgrade.
Would immutable releases have prevented this?
The CEO's stated cause is that the setting was off and a privileged account could edit existing releases[4]. With it on for those releases, overwriting their assets would not have been possible, per GitHub's description of what is locked[7]. It would not stop a hijacked account from publishing a new release, which is why verification on the user side still matters.
Sources
- OVHcloud: GHSA-862f-55f5-vmvw, ovhcloud-cli security incident (accessed 20 October 2026)
- ovh/ovhcloud-cli issue #300 (accessed 20 October 2026)
- ovh/ovhcloud-cli release v0.16.0 (accessed 20 October 2026)
- BleepingComputer: OVHcloud CLI releases backdoored on GitHub to steal developer secrets (accessed 20 October 2026)
- The Hacker News: hackers hijack five OVHcloud CLI releases (accessed 20 October 2026)
- OpenSourceMalware: GlassWorm hacks OVH Cloud's CLI tool (accessed 20 October 2026)
- GitHub Docs: immutable releases (accessed 20 October 2026)
- GitHub Docs: preventing changes to your releases (accessed 20 October 2026)
- GitHub Docs: verifying the integrity of a release (accessed 20 October 2026)
Written by
WOWHOW
The WOWHOW team brings 14+ years of production engineering experience. Every tool and product in the catalog is built, tested, and curated in-house.
Monday memo · free
One insight, every Monday. 7am IST.
1 field report, 3 links, 1 tool we actually use. No fluff, no spam.
Beyond the writing
Need production-ready templates?
Free browser tools with no signup, plus premium dev templates and starter kits.
Comments · 0
Beta: comments are stored locally on your device and not visible to other readers.
No comments yet. Be the first to share your thoughts.