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.
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.
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
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.
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
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.
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
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.
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
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.
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
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.
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
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.
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
🛡 How to Defend Against This Chain
~/.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.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.gh release verify-asset, which StepSecurity recommends for v0.16.0.