OVHcloud CLI Releases Were Swapped for a Secret-Stealing Build for 94 Minutes

Attackers used a hijacked developer account to replace OVHcloud CLI v0.11.0 to v0.15.0 binaries on GitHub with a secret-stealing build on October 19. If you installed or updated in that window, rotate every secret on the machine and move to v0.16.0.

Advisory card: OVHcloud CLI release assets swapped, versions v0.11.0 to v0.15.0 malicious, v0.10.0 and v0.16.0 clean, window October 19 12:47 to 14:21 UTC
Advisory card by JDNEER. Sources: OVHcloud, GitHub issue #300, OpenSourceMalware.

Attackers swapped the release binaries of five versions of OVHcloud's official command-line tool, ovhcloud, for a build designed to steal secrets from the machine it runs on. The tampered files sat on the project's GitHub release pages for about 94 minutes on October 19 before OVHcloud deleted them. Anyone who installed or updated the CLI on macOS, Linux or Windows from those release pages during that window should treat every secret on that machine as exposed.

OVHcloud CEO Octave Klaba announced on X that the compromised versions are v0.11.0, v0.12.0, v0.13.0, v0.14.0 and v0.15.0, that v0.10.0 and the new v0.16.0 are clean, and that the attacker "used the GitHub account of one of the developers and added a binary whose job is to retrieve secrets from the disk." He called the binary's quality poor "but it can go all the way," and told affected users to change all the secrets on their disk. This is a supply-chain compromise, not a software vulnerability, and no CVE has been assigned.

Timeline

OVHcloud's statements use Paris time (UTC+2). The UTC times below come from Klaba's posts, the public GitHub issue #300, and the server-side GitHub records analyzed by OpenSourceMalware.

UTC (Oct 19)ManilaEvent
12:47Oct 19, 8:47 PMFirst swapped files land on v0.15.0
12:57 to 13:128:57 to 9:12 PMChecksums and the other releases swapped
13:509:50 PMA user files issue #300 after a pinned hash fails in CI
14:2110:21 PMOVHcloud deletes all swapped files
16:52Oct 20, 12:52 AMKlaba posts the alert on X
17:16Oct 20, 1:16 AMClean, immutable v0.16.0 published
20:29Oct 20, 4:29 AMKlaba declares the incident closed

The issue was caught by a user, not by OVHcloud. Their CI job pinned the SHA-256 of ovhcloud-cli_Linux_arm64.tar.gz from v0.15.0 and started failing. In the issue, they showed that the new file was a local, "dirty" Go build of a later commit, uploaded by the account HassenBF rather than by the release pipeline, and asked whether it was intentional. OVH maintainer Romain Beuque replied that all the binaries involved were deleted at 16:21 Paris time and then shipped v0.16.0, saying the release is immutable "so the assets attached to it can be trusted." OVHcloud has promised a detailed post-mortem "in the coming days."

How it happened

No source code changed. The attacker replaced files attached to releases that had been published months earlier, using an account that already had write access to the repository. In his follow-up post, Klaba said the CI/CD pipelines, including unit tests, functional tests and CVE detection, were not affected. The gap was that GitHub's release immutability option had not been turned on, so a user with the right permissions could modify existing releases directly on GitHub without passing through OVHcloud's CI/CD. OVHcloud has since enabled it.

According to OpenSourceMalware, only the mainstream builds were replaced: macOS on Apple silicon and Intel, Linux x86_64 and arm64, Windows x86_64, and each release's checksums.txt, so the published hashes matched the swapped files. The Linux and Windows i386 builds, the Windows arm64 build and the WebAssembly build were left alone. The issue reporter confirmed the swaps directly for v0.13.0 to v0.15.0; for v0.11.0 and v0.12.0, the researchers rely on OVHcloud's statement and the files left behind.

VersionFirst publishedSwapped Oct 19
v0.10.0Mar 2, 2026No (clean)
v0.11.0Apr 14, 2026Yes, per OVHcloud
v0.12.0May 29, 2026Yes, per OVHcloud
v0.13.0Aug 25, 2026Yes, confirmed in #300
v0.14.0Aug 31, 2026Yes, confirmed in #300
v0.15.0Sep 16, 2026Yes, confirmed in #300
v0.16.0Oct 19, 2026No (clean, immutable)

OpenSourceMalware also found that the HassenBF account, which belongs to a real OVH contributor, appears to have been compromised since at least March 5, 2026, when four of its personal repositories were force-pushed with a hidden JavaScript loader. That loader fetches its next stage through a Solana wallet memo, and the wallet appears on public GlassWorm indicator lists. The researchers stress that linking the March activity to the October release swap is their inference, based on the shared account.

What the payload did

Very little is public. OVHcloud says the binary looks for secrets on disk, and Klaba said the company is still analyzing it. OVHcloud deleted the swapped files before anyone archived them, so OpenSourceMalware says it has not analyzed the payload, and neither OVHcloud nor the researchers have published which paths it reads, where it sends data, or any network indicators. The one known-bad file hash comes from the issue reporter's CI.

Indicators

  • Swapped file: v0.15.0 ovhcloud-cli_Linux_arm64.tar.gz, SHA-256 3833daffcaaaab27e4e0e0833240ffcb1df8df648f4ec0bc4a75c176e28933cb (the original was 5c2beb56e6d83a4b426565a1557791ef759316abcc4effb38dd627c90aeb80e0)
  • Build metadata of the swapped binary: module version v0.15.1-0.20261013083505-5ead8ef9b43d+dirty, vcs.revision=5ead8ef9b43d354dfb5caadff803b11afc8c5c58, vcs.modified=true
  • Uploader: GitHub account HassenBF
  • Related loader, per OpenSourceMalware: preinstall.js, SHA-256 43df42fd79f6f81e530892b54634598770d6e496796a863c596e616bcb3fec70; Solana wallet BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC; marker file ~/init.json on macOS

Are you affected?

OpenSourceMalware says you are affected if, between 12:47 and 14:21 UTC on October 19 (8:47 to 10:21 PM Manila), you installed or updated the CLI on macOS, Linux x86_64 or arm64, or Windows x86_64 using the official install.sh script, a direct download from the releases page, or a CI job or Dockerfile that fetches from github.com/ovh/ovhcloud-cli/releases/download/. You are not affected if you used go install, built from source, used the ovhcom/ovhcloud-cli Docker image, or did not install or update during the window.

The researchers also list Homebrew as an affected route. However, the Homebrew cask that OVHcloud published for v0.15.0 pins the SHA-256 of the original archives, and Homebrew checks downloads against it, so a Homebrew install during the window should have failed with a checksum mismatch rather than installing the swapped file. OVHcloud has not addressed this, so Homebrew users who installed or upgraded during the window should still check.

Find the binary and when it was installed. Look for a timestamp inside the window. On Linux:

bin=$(command -v ovhcloud)
ls -lL --time-style=full-iso "$bin"

On macOS, use stat -L -f '%Sm' "$(command -v ovhcloud)".

Inspect it without running it. If Go is installed, read the build info:

go version -m "$(command -v ovhcloud)" | grep -E 'mod|vcs'

A line reading vcs.modified=true or a module version ending in +dirty marks the swapped build. OpenSourceMalware also notes that ovhcloud version prints the tag on clean builds but not on the swapped one; be aware that this command runs the binary.

Homebrew users: check the installed version and when it was installed:

brew list --cask --versions ovhcloud-cli
ls -l "$(brew --caskroom)/ovhcloud-cli"
  • Check any archive you kept. Run sha256sum on it (shasum -a 256 on macOS) and compare with the hashes above or with the checksums in the v0.16.0 release.
  • If you ran a swapped binary, rotate everything from a different, clean machine. OVHcloud's advice is to change all the secrets on your disk. OpenSourceMalware's list includes OVHcloud API application keys and consumer keys (including ~/.ovh.conf), other cloud provider credentials, SSH keys, .npmrc, .pypirc and .netrc tokens, Kubernetes configs and anything in .env files. Revoke the old OVHcloud API credentials rather than only issuing new ones, and include CI runners that fetched the CLI during the window.

Remove the binary and install v0.16.0 or later.

brew update && brew upgrade --cask ovh/tap/ovhcloud-cli
# or, without Homebrew:
u=https://raw.githubusercontent.com/ovh/ovhcloud-cli
curl -fsSL "$u/main/install.sh" | sh

The v0.16.0 release ships a GitHub release attestation. With the GitHub CLI, you can check a downloaded archive using gh attestation verify ovhcloud-cli_Linux_x86_64.tar.gz --repo ovh/ovhcloud-cli.

The issue reporter's habit is the broader lesson: pinning and checking the hash of every third-party binary in CI is what flagged the swap about an hour after it began, and the files were deleted 94 minutes after the first one went up. Projects that publish binaries on GitHub can close the same gap by turning on immutable releases, as OVHcloud has now done.