Get the Zoom link
Cloud Security Office Hours Banner

OVHcloud CLI Release Swap 2026

Step-by-step kill chain mapped to MITRE ATT&CK Cloud, sourced from official post-mortems and primary technical analyses.

October 2026 Critical OVHcloud CLI / GitHub Releases

OVHcloud CLI Release Swap - IDE Extension on a Personal Laptop → Stolen Keys for a Developer's GitHub Account → Stealer Builds Uploaded Over Five Old Releases → Checksums Replaced to Match → Cloud and Kubernetes Credentials Targeted → Caught by a Pinned Hash in CI

OVHcloud published GitHub security advisory GHSA-862f-55f5-vmvw on October 20, 2026. It describes how, the day before, someone using an OVHcloud developer's compromised GitHub account replaced the binaries on five existing releases of the company's command-line tool, ovhcloud-cli v0.11.0 through v0.15.0, with a local build carrying a credential stealer. The swapped files were available from 12:47 to 14:21 UTC and went after cloud, Kubernetes, Terraform and SSH credentials and AI coding assistant data. On at least three of the releases the checksums file was replaced as well, so the published hashes matched the new files. A customer whose CI pinned one archive's SHA-256 reported the mismatch, and OVHcloud removed the binaries 31 minutes later, suspended the account, made releases immutable across its GitHub organization and shipped a clean v0.16.0. OVHcloud traces the compromise to an extension the developer installed on a personal MacBook in October 2025. Two caveats belong next to the headline. The GlassWorm name rests on a Solana wallet and a force-push technique. OpenSourceMalware found the wallet, which appears on public GlassWorm indicator lists, in loaders force-pushed to the account's personal repositories in March 2026, and matched the amend-and-force-push method to the ForceMemo campaign, as StepSecurity also does; OVHcloud found the same wallet in the extension and says it belongs to GlassWorm. OpenSourceMalware calls the link between the March misuse and the October uploads its own inference. And OVHcloud's figure of about 250 is a download count; none of the sources reviewed here gives a number of machines that ran the binary or reports stolen credentials being used.

12:47 to 14:21 UTC on October 19, the window the swapped binaries were available, per OVHcloud (which gives the duration as 1h33)
5 releases × 5 platform binaries replaced, v0.11.0 through v0.15.0, per OVHcloud
~250 downloads during the window, from OVHcloud's download statistics
Threat actor: OpenSourceMalware's headline names GlassWorm, on the strength of a wallet on public GlassWorm indicator lists and a matching force-push technique in the account's March activity, though its report calls the March-to-October link an inference; OVHcloud ties the 2025 extension's wallet to GlassWorm and traces the account's compromise to that extension, without naming who made the October uploads
📄 OVHcloud - GHSA-862f-55f5-vmvw, ovhcloud-cli security incident ↗ 📄 ovhcloud-cli issue #300 - Customer report of replaced release assets ↗ 📄 StepSecurity - OVHcloud CLI Compromised via GitHub Release Swap ↗ 📄 OpenSourceMalware - Glassworm Hacks OVH Clouds CLI tool ↗
⚡ Initial Access: An Extension on a Personal Laptop
01
In October 2025 the developer installed the color-picker-universal extension on a personal MacBook, and OVHcloud traces the compromise to it
T1176.002 - IDE Extensions

OVHcloud's advisory places the start a year before the swap. On October 20, 2025, the developer whose GitHub account was later used installed the extension color-picker-universal 2.8.91 on a personal MacBook. A persistent NodeJS service was registered through a plist and communicated with 162.33.177[.]177. The extension makes RPC calls with a Solana wallet that OVHcloud says is known to belong to the GlassWorm threat actor, citing The Hacker News's March 2026 reporting.

That reporting describes GlassWorm as a campaign that spreads through malicious VS Code and Cursor extensions and has moved on to taking over GitHub accounts with stolen tokens. OVHcloud does not say what the extension took from the laptop. It says the developer's OVHcloud laptop had not been compromised, as far as it knew when it wrote the advisory. As in the 3CX / X_TRADER compromise of 2023, the chain began on an employee's personal computer.

Installed: color-picker-universal 2.8.91, 2025-10-20
Machine: the developer's personal MacBook
Persistence: a NodeJS service registered with a plist
Contacted: 162.33.177[.]177
Wallet in the extension: BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC, GlassWorm per OVHcloud
IDE ExtensionPersonal DeviceGlassWormT1176.002
🔐 Persistence: A Developer Account Misused Since March
02
By March 2026 the attacker was using the developer's GitHub account, which could upload assets to ovhcloud-cli releases
T1078.004 - Cloud Accounts

OpenSourceMalware built its timeline from GitHub's server-side records rather than commit dates, which the pusher controls. On March 5 and 6, 2026, four of the account's personal repositories were force-pushed with a hidden preinstall.js loader, or the same decoder inlined in a source file. The loader reads a link from the memo of a Solana transaction, using the same wallet as the extension. OpenSourceMalware calls March 5 the earliest server-verified use of the account by the attacker, about 228 days before the swap, and treats it as an upper bound on when the attacker had a token. OVHcloud's advisory also records the March compromise and the reused wallet.

The account was the developer's personal GitHub account, registered to OVHcloud's GitHub organization. OVHcloud allows that, requires two-factor authentication on every account and keeps a central inventory of them. The account was not a public member of the organization and had no commits in ovh/ovhcloud-cli, yet it held the write access needed to upload release assets; OpenSourceMalware infers that access most likely came through the repository's owners team. OVHcloud says the October uploads used stolen keys rather than the personal MacBook, and does not say what kind of keys or how they were taken. OpenSourceMalware names an infostealer on the developer's machine or a stolen token as the likeliest paths.

Earliest attacker use: 2026-03-05, server-verified, per OpenSourceMalware
March activity: four personal repositories force-pushed with a loader
Account: personal GitHub account in OVHcloud's organization, 2FA required
October uploads: "stolen keys", type not disclosed
Same actor in March and October: OpenSourceMalware's inference
GitHub AccountForce PushSolana MemoT1078.004
⚡ Initial Access: A Local Build of a Real Commit
03
The attacker compiled the CLI locally from an October 13 commit, with a stealer module named envchecker added
T1195.002 - Compromise Software Supply Chain

The go version -m output that the customer posted in issue #300, and that OVHcloud reproduces, shows a pseudo-version built from commit 5ead8ef with uncommitted changes. That commit was merged to main on October 13 and was never a release tag. The build used -ldflags="-s -w" and lacked the version flag that the project's GoReleaser configuration sets, so it did not come from the release pipeline, and the v0.15.0 tag still pointed to its original commit. OVHcloud describes the binary as the original CLI recompiled with stripped malicious Go code, an envchecker module, and says the source code and build chain were not affected.

Two analyses read an earlier event differently. On October 15 the account deleted two branches in ovh/ovhcloud-docs, dev/test-changest and test/trigger-probe. StepSecurity says the names read like CI-trigger probing. OpenSourceMalware notes the account created both branches in May and September, reads the deletion as cleanup, and says GitHub's data cannot show whether the owner or the attacker made it. The +dirty suffix is a weak marker: The Hacker News found it on the clean v0.16.0 binary too, and StepSecurity names the pseudo-version and the missing version flag as the reliable ones.

Built from: 5ead8ef, merged to main 2026-10-13 08:35 UTC
Version string: v0.15.1-0.20261013083505-5ead8ef9b43d+dirty
Missing: the release pipeline's version ldflag
Added: envchecker stealer module, stripped
Untouched: source code and build chain, per OVHcloud; the v0.15.0 tag, per issue #300
Go BuildTrojanized BinaryBuild ProvenanceT1195.002
⚡ Initial Access: Same File Names on Five Old Releases
04
On October 19 the account uploaded the stealer builds over five existing releases and replaced checksum files to match
T1036.005 - Match Legitimate Resource Name or Location

OVHcloud's timeline, converted to UTC: the v0.15.0 Darwin binary was replaced at 12:47, all five targeted v0.15.0 binaries by 12:57, and the binaries on v0.14.0 back to v0.11.0 by 13:30. The replaced files were the Darwin arm64 and x86_64, Linux arm64 and x86_64, and Windows x86_64 builds; the i386, Windows arm64 and WebAssembly builds were left alone. The customer's capture from the GitHub releases API covers only v0.15.0, v0.14.0 and v0.13.0, replaced between about 12:47 and 13:12, and shows the checksums file on each of them replaced after the binaries it checked, the last at 13:11. StepSecurity and OpenSourceMalware extend that capture to all five releases and put the end at about 13:12, which OpenSourceMalware says it could not confirm independently; OVHcloud's timeline has all five replaced by 13:30. OpenSourceMalware infers the same set of files for v0.11.0 and v0.12.0. OVHcloud's advisory does not mention the checksums file.

OVHcloud calls the main issue a repository not configured for release immutability, so an account with write access could replace assets on releases published weeks or months earlier, at unchanged URLs. As in the tj-actions/changed-files compromise of 2025, where a stolen token moved existing version tags, a version people already trusted began delivering different code. A customer whose CI pinned the SHA-256 of the v0.15.0 Linux arm64 archive saw the job fail and opened issue #300 at 13:50 UTC. OVHcloud began investigating at 13:57, removed all the malicious binaries at 14:21, and found no changes by the account in its other repositories.

First replacement: 12:47 UTC, the v0.15.0 Darwin binary
Last replacement: by 13:30 UTC per OVHcloud; about 13:12 per StepSecurity and OpenSourceMalware, extending the customer's capture of v0.13.0 to v0.15.0
Replaced: Darwin arm64 and x86_64, Linux arm64 and x86_64, Windows x86_64
Checksums file: replaced on v0.13.0 to v0.15.0 per the customer; inferred for v0.11.0 and v0.12.0
Caught by: a pinned SHA-256 in a customer's CI, issue #300 at 13:50 UTC
Removed: 14:21 UTC
GitHub ReleasesMutable AssetsChecksumsT1036.005
🔀 Execution: Install Paths That Checked Nothing
05
The install script and the CLI's own upgrade command fetched the swapped archives with no hash check, while Homebrew's pinned cask would have refused them
T1204.002 - User Execution: Malicious File

StepSecurity and The Hacker News agree that install.sh never checks a hash, and StepSecurity says the CLI's ovhcloud upgrade command verifies nothing either. The Hacker News limits that path to v0.12.0, v0.13.0 and v0.14.0 installs on macOS or Linux that were set up by the script or by hand; on Homebrew and go install setups the command only prints what to run. Direct downloads and CI jobs that fetched the archives without a pinned hash were exposed for the same reason. OpenSourceMalware, StepSecurity and The Hacker News all say that go install, source builds and the Docker image were not exposed. OVHcloud counts about 250 downloads in the window. That is a download figure, and no source gives a count of machines that ran the binary.

The sources disagree on two paths. OpenSourceMalware listed a Homebrew install or upgrade as exposed. The Hacker News checked the tap's history and found no change between the September cask and the v0.16.0 cask, and StepSecurity says the cask pins per-architecture SHA-256 hashes, so Homebrew would have refused the swapped file. StepSecurity also reports that install.sh never worked on arm64 Linux, because it requests an asset name that was never published, which would leave arm64 Linux exposed only through the upgrade command or a manual download. The exposure lists from OpenSourceMalware and The Hacker News do not make that distinction.

No hash check: install.sh, ovhcloud upgrade (v0.12.0 to v0.14.0 script or manual installs, per The Hacker News), direct download, unpinned CI fetches
Refused the swap: Homebrew's cask, per StepSecurity and The Hacker News
Not exposed: go install, source builds, the Docker image
Downloads in the window: about 250, per OVHcloud
install.shSelf-UpdateHomebrewT1204.002
🔑 Credential Access: What a Developer Machine Holds
06
Each run copied cloud, Kubernetes, Terraform, SSH and AI-assistant credential files into an envchecker folder that is never deleted
T1552.001 - Credentials In Files

OVHcloud's advisory lists what the stealer gathers: AWS credentials and configuration including S3, Google Cloud, Azure, DigitalOcean's doctl, Docker, Kubernetes, Terraform credentials, npm configuration, SSH keys, .netrc and the global Git configuration. It also takes local data from AI coding tools: the VS Code and Cursor state databases, the Continue extension's index, Sourcegraph Cody chat histories, the OpenCode database, Hermes agent sessions and the Claude agent's configuration directory. Besides copying files, it writes out credentials collected through various commands, which the advisory does not list.

On each run the binary creates a new folder in the temporary directory named envchecker- followed by nine or ten digits, copies the files into it and archives it. OVHcloud says the folder is never deleted, which makes it a way to check for exposure. The advisory's path list does not include ~/.ovh.conf, where The Hacker News notes the CLI keeps OVH API credentials, but OVHcloud's advice covers every secret stored on an affected machine.

Cloud: ~/.aws/credentials, ~/.config/gcloud/access_tokens.db, ~/.azure/msal_token_cache.json, ~/.config/doctl/config.yaml
Clusters and infrastructure: ~/.kube/config, ~/.terraform.d/credentials.tfrc.json, ~/.docker/config.json
Developer: ~/.ssh, ~/.netrc, ~/.gitconfig
AI tools: ~/.claude, ~/.hermes/sessions, the Cursor and VS Code state.vscdb files
Staging: envchecker-<9 or 10 digits> in the temp directory, never deleted
Cloud CredentialsKubeconfigTerraformAI Agent DataT1552.001
📤 Exfiltration: A Solana Call, Then an Upload
07
The stealer made Solana RPC calls through a public endpoint and uploaded the archive to 45.32.148[.]174
T1041 - Exfiltration Over C2 Channel

OVHcloud calls the mechanism rudimentary, with one more elaborate part. The stealer picks one of five public Solana RPC endpoints at random and makes its calls with the wallet BHaDaVbdCYFNaKZGn7yLXFneWoJHZgLiBYkHxVrjyALF, then uploads the archive to hxxps://45.32.148[.]174/upload. OVHcloud warns that the threat actor can change this URL at any moment. In StepSecurity's replay, which ran its own rebuild because the real binaries were deleted, the upload was a JSON POST shaped like a Solana RPC request, with the archive base64-encoded inside it. StepSecurity credits that format to the advisory, which does not describe it.

The stealer used a different wallet. OVHcloud lists BHaDa... for the stealer; BjVe... is the wallet it ties to GlassWorm, found in the 2025 extension and the March loader. When The Hacker News wrote, no copy of a swapped archive had been analyzed in public, so nothing from the October binary had been tied to GlassWorm. OVHcloud's advisory lists five samples on VirusTotal and thanks Ivan Kwiatkowski and the VirLabs.ai malware analysis platform, ties the extension's wallet to GlassWorm, and does not name the actor behind the October uploads.

Solana RPC: one of five public endpoints, chosen at random
Wallet used by the stealer: BHaDaVbdCYFNaKZGn7yLXFneWoJHZgLiBYkHxVrjyALF
Upload: hxxps://45.32.148[.]174/upload, which OVHcloud says can change
Different wallet: BjVe... in the 2025 extension and the March loader
Solana RPCExfiltrationIOCT1041

🛡 How to Defend Against This Chain

If you ran a swapped binary, rotate first, and do it from a different machine. OVHcloud's advisory lists the steps in this order: change or deactivate the secrets for every relevant service as soon as possible, delete the compromised binaries, then install v0.16.0. StepSecurity and OpenSourceMalware both say to rotate from a different machine, and StepSecurity and The Hacker News point out that updating the CLI revokes nothing already copied. None of these four sources describes a revocation trigger or destructive behavior in this stealer, unlike the watcher in the CHAINDROP / keyv worm, so nothing here argues for waiting. The strongest evidence is OVHcloud's advisory, which rests on the actual binaries: it gives their MD5 hashes, lists five samples on VirusTotal, thanks the VirLabs.ai malware analysis platform, and describes only collection and exfiltration. The Hacker News wrote before the advisory appeared, and StepSecurity's replay ran its own rebuild because the originals were deleted. Include OVH API keys, which OpenSourceMalware and StepSecurity both list for rotation; the CLI keeps them in ~/.ovh.conf. OVHcloud says the stealer copies what it collects into the envchecker-* folder and never deletes it, so the folder is itself a copy of those secrets; StepSecurity says to delete it along with the binary, and to rebuild any machine you cannot show is clean.
Check for exposure without running the binary. Do not run a suspect copy, even to print its version; OVHcloud's advisory says not to run it. Instead, as OVHcloud advises, compare its MD5 against the hashes in the advisory's appendix, look for an envchecker-* folder in the temporary directory, or go by when you downloaded it: OVHcloud says only copies downloaded between 12:47 and 14:21 UTC on October 19 are affected. go version -m reads the build information from the file without executing it and shows the 5ead8ef pseudo-version; The Hacker News, StepSecurity and OpenSourceMalware all describe that check. StepSecurity and OpenSourceMalware also list ovhcloud version as a quick tell, but that runs the program: OVHcloud says every run starts a new collection, StepSecurity's own replay, run against its rebuild, finished exfiltrating about two seconds after that command, and The Hacker News calls running a suspect binary inadvisable. For CI, StepSecurity says to audit any job that fetched these releases between 12:47 and 14:21 UTC on October 19 and to treat credentials reachable from those runners as exposed.
Pin artifact hashes somewhere the publisher's account cannot rewrite. The checksums file sat in the same release as the binaries and was replaced with them, so any check against it passed. The customer's CI pinned its own copy of one hash and failed, and Homebrew's cask, kept in a separate repository, pinned the original hashes. The install script and the upgrade command checked nothing. If you ship a CLI, make the installer and the self-update path verify a hash or attestation that the release page cannot change; if you consume one, pin the hash in your pipeline.
Turn on immutable releases, and remember they cover only new ones. OVHcloud names the missing immutability setting as the main issue and has applied it to every repository in its organization. GitHub's documentation says immutability applies only to future releases, so a release published before you enable it can still have its assets replaced by an account with write access. An immutable release also gets an attestation that you can check with gh release verify-asset, which StepSecurity recommends for v0.16.0.
Treat every account that can publish a release as part of your build system. The uploads came from a developer's personal GitHub account in an organization that required 2FA, and they went through with what OVHcloud calls stolen keys. Two-factor authentication applies at sign-in, and a token issued earlier is used without it. OVHcloud's next steps include linking any function that can publish a release to its centralized IAM, signing commits and merges, and reviewing every GitHub account attached to its organization; OpenSourceMalware notes v0.16.0 was published by a service account rather than a person. Limit release write access to the pipeline's identity, and keep publishing credentials off machines that run unvetted IDE extensions.
Alert on release assets that change after publication, and on amended force-pushes. The customer confirmed the swap through the GitHub releases API, which records each asset's uploader and timestamps: a different account had replaced files on releases published weeks or months earlier. OpenSourceMalware recommends alerting on force-pushes to long-idle repositories using GitHub's server-side activity timestamps rather than commit dates, and blocking Solana RPC endpoints from build hosts that have no reason to reach them.

Related defense topics