Ilustración abstracta de pintura fluida en tonos azul marino, rojo y blanco para la noticia: OVHcloud CLI sirvió un stealer de secretos desde GitHub durante 94 minutos

Ciberataques

OVHcloud CLI sirvió un stealer desde GitHub durante 94 minutos

OVHcloud CLI distribuyó desde GitHub binarios con un stealer en cinco versiones, de la v0.11.0 a la v0.15.0, con unas 250 descargas en 94 minutos.

OVHcloud ha confirmado que un atacante usó la cuenta de GitHub de uno de sus desarrolladores para sustituir, el 19 de octubre de 2026, los binarios de cinco versiones ya publicadas de OVHcloud CLI (de la v0.11.0 a la v0.15.0) por una compilación con un stealer de credenciales. Los archivos estuvieron disponibles 94 minutos, se descargaron unas 250 veces y la compañía ha activado la inmutabilidad de releases que GitHub ofrece desde octubre de 2025 y que su repositorio no tenía encendida.

Qué ha pasado

El lunes 19 de octubre a las 14:47, hora peninsular (12:47 UTC), la cuenta de GitHub HassenBF empezó a borrar y volver a subir, con el mismo nombre, los archivos de la release v0.15.0 de ovhcloud-cli, la herramienta de línea de comandos con la que OVHcloud propone gestionar sus servicios desde la terminal. En los minutos siguientes hizo lo mismo con las releases v0.14.0 y v0.13.0, y el aviso posterior de la compañía amplía la lista a la v0.12.0 y la v0.11.0. Las URL de descarga no cambiaron, cambiaron los hashes, y el archivo checksums.txt de cada release se reescribió para que cuadrase con los binarios nuevos.

Lo detectó un cliente. El usuario alink-tothepast abrió la issue #300 a las 15:50 porque su pipeline de integración continua fijaba el SHA-256 del archivo Linux arm64 de la v0.15.0 y había empezado a fallar. En el informe aportaba la huella original (5c2beb56…), la nueva (3833daff…) y la salida del comando que muestra con qué commit se compiló el binario. El equipo de OVHcloud borró los archivos maliciosos a las 16:21 y publicó a las 19:16 la v0.16.0 con el tag firmado y la release marcada como inmutable.

Octave Klaba, fundador de OVHcloud, lo contó en X a las 18:52. Según recoge Help Net Security, describió el añadido como un binario cuya misión es «retrieve secrets from the disk» (recuperar secretos del disco) y pidió a los afectados: «If you are affected, please change all the secrets on your disk» (si te afecta, cambia todos los secretos de tu disco). Al día siguiente, 20 de octubre, OVHcloud publicó el aviso GHSA-862f-55f5-vmvw con gravedad alta, la cronología completa, los hashes de los binarios y la lista de archivos que roba el malware. El aviso agradece el informe a alink-tothepast y el análisis a Ivan Kwiatkowski y la plataforma VirLabs.ai.

Es la tercera pieza en una semana sobre software legítimo que reparte malware desde su propio canal, después del backdoor servido desde la web de Rank Math PRO y de las actualizaciones de AOMEI Backupper que instalaban un backdoor. En este caso el canal es la página de releases de GitHub, la que casi todo el mundo da por buena.

Detalles técnicos

Dato

Valor

Producto

OVHcloud CLI (binarios ovhcloud y ovhcloud.exe publicados en GitHub)

Versiones afectadas

v0.11.0, v0.12.0, v0.13.0, v0.14.0 y v0.15.0 descargadas entre las 14:47 y las 16:21 (hora peninsular) del 19 de octubre de 2026

Versiones corregidas

v0.16.0, publicada el 19 de octubre a las 19:16 como release inmutable con tag firmado

Plataformas afectadas

macOS arm64 y x86_64, Linux arm64 y x86_64, Windows x86_64

Explotación activa

Sí, unas 250 descargas en 94 minutos según OVHcloud

Gravedad

Alta (aviso GHSA-862f-55f5-vmvw de OVHcloud)

CVE

Sin CVE asignado

El binario no salió de la cadena de compilación de OVHcloud. Según la issue #300 y el análisis de OpenSourceMalware, se compiló en local a partir del commit 5ead8ef del 13 de octubre (que no es el del tag v0.15.0, 760fd72), con cambios sin confirmar en el árbol de trabajo y sin el parámetro de versión que GoReleaser inyecta en las releases oficiales. El diagrama de OpenSourceMalware resume el recorrido: del portátil del atacante a la API de releases de GitHub y de ahí a las rutas de instalación, sin que la CI llegara a ejecutarse.

Diagrama de OpenSourceMalware con el recorrido del binario malicioso de OVHcloud CLI, desde el equipo del desarrollador hasta las rutas de instalación, sin pasar por la CI
Fuente: OpenSourceMalware, «Glassworm Hacks OVH Clouds CLI tool»

Esa salida es la que delató la sustitución. El reportero la obtuvo con go version -m sobre el binario descargado y la copió en la issue.

mod   github.com/ovh/ovhcloud-cli  v0.15.1-0.20261013083505-5ead8ef9b43d+dirty
build -ldflags="-s -w"
build vcs.revision=5ead8ef9b43d354dfb5caadff803b11afc8c5c58
build vcs.time=2026-10-13T08:35:05Z
build vcs.modified=true

Una release legítima de la v0.15.0 muestra la versión 0.15.0 y el commit 760fd72. La pseudoversión v0.15.1-0.2026… y el sufijo +dirty indican una compilación de un commit posterior con modificaciones locales.

El aviso de OVHcloud explica qué hace esa modificación. El código malicioso se inyectó en la CLI mediante un módulo llamado envchecker que reúne todas las funciones del stealer. Al ejecutarse, crea en el directorio temporal del sistema una carpeta envchecker- seguida de nueve o diez dígitos, que nunca borra, copia en ella los archivos de credenciales que encuentra, la comprime y la sube. El aviso enumera las rutas que busca.

Categoría

Rutas que busca el módulo envchecker

Editores y asistentes de código

~/.config/Code/User/globalStorage/state.vscdb, ~/.config/Cursor/User/globalStorage/state.vscdb, índices de Continue, historial de chat de Cody, opencode.db, ~/.hermes/sessions, ~/.hermes/.hermes_history y ~/.claude

Nubes públicas

~/.aws/credentials, ~/.aws/config, ~/.aws/cli/cache, ~/.config/gcloud/credentials.db, ~/.config/gcloud/access_tokens.db, ~/.config/gcloud/configurations/config_default, ~/.azure/azureProfile.json, ~/.azure/clouds.config, ~/.azure/config y ~/.azure/msal_token_cache.json

Contenedores y Kubernetes

~/.docker/config.json, ~/.dockercfg y ~/.kube/config

Infraestructura como código

~/.config/doctl/config.yaml y ~/.terraform.d/credentials.tfrc.json

Acceso y Git

~/.ssh, ~/.netrc y ~/.gitconfig

Para la exfiltración, el binario hace llamadas RPC a Solana contra uno de cinco endpoints públicos elegido al azar (solana.drpc[.]org, solana-rpc.publicnode[.]com, solana.api.pocket[.]network, api.mainnet-beta.solana[.]com y solana.api.onfinality[.]io) con la cartera BHaDaVbdCYFNaKZGn7yLXFneWoJHZgLiBYkHxVrjyALF, y después sube el archivo comprimido a 45.32.148[.]174 por el puerto 443, ruta /upload. OVHcloud avisa de que esa dirección puede cambiar en cualquier momento. El diagrama siguiente ordena los siete pasos que describen la issue y el aviso.

Diagrama con los siete pasos del stealer de OVHcloud CLI, desde la cuenta de GitHub robada hasta la subida del archivo con credenciales al servidor del atacante
Elaboración propia con datos de OVHcloud y de la issue #300

La tabla reúne los indicadores que publica OVHcloud y los que aporta la issue para el archivo Linux arm64.

Indicador

Valor

MD5 ovhcloud (Darwin_arm64)

6f2f086239f3d88eb2750e871901927d

MD5 ovhcloud (Darwin_x86_64)

347e65eb7f2d78d1c6872690272a6cc3

MD5 ovhcloud (Linux_arm64)

01f57206d37c28cf711677f612052913

MD5 ovhcloud (Linux_x86_64)

301bff0b51980b9e76c93633e7cfd3bd

MD5 ovhcloud.exe (Windows x86_64)

6a3cf153338c416169cda2fe704c8848

SHA-256 del archivo Linux arm64 sustituido (v0.15.0)

3833daffcaaaab27e4e0e0833240ffcb1df8df648f4ec0bc4a75c176e28933cb

SHA-256 del archivo Linux arm64 original (v0.15.0)

5c2beb56e6d83a4b426565a1557791ef759316abcc4effb38dd627c90aeb80e0

Commit del binario malicioso

5ead8ef9b43d354dfb5caadff803b11afc8c5c58 (vcs.modified=true)

Carpeta en el directorio temporal

envchecker- seguido de 9 o 10 dígitos

Servidor de subida

45.32.148[.]174:443, ruta /upload

Cartera de Solana del stealer

BHaDaVbdCYFNaKZGn7yLXFneWoJHZgLiBYkHxVrjyALF

Cartera de Solana del loader de marzo (OpenSourceMalware)

BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC

OVHcloud ha subido las cinco muestras a VirusTotal y las enlaza desde el apéndice del aviso. OpenSourceMalware, que publicó su análisis la noche del 19 de octubre, no había podido conseguir una copia porque la compañía borró los archivos antes de que nadie los archivase.

Lo que sí pudo analizar OpenSourceMalware es el historial de la cuenta usada para subir los binarios. Pertenece a un colaborador legítimo de OVHcloud y, el 5 de marzo de 2026, alguien reescribió por la fuerza el historial de cuatro de sus repositorios personales (treasure-hunt-game, crwn-clothing, next-dashboard y padel-bot) para plantar un loader oculto. En tres de ellos el loader es un archivo preinstall.js de una sola línea y 35,8 KB que decodifica caracteres Unicode invisibles y los pasa a eval. Las capturas de OpenSourceMalware muestran los tres archivos con la misma línea.

Capturas de GitHub de tres repositorios personales del colaborador de OVHcloud con el archivo preinstall.js ofuscado de una sola línea y 35,8 KB
Fuente: OpenSourceMalware, «Glassworm Hacks OVH Clouds CLI tool»

El loader consulta la cartera de Solana BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC a través de una lista de nueve endpoints RPC para obtener la segunda fase, un método que el laboratorio relaciona con GlassWorm. El fragmento que reproducimos muestra la dirección y los endpoints tal como aparecen en el código decodificado.

Fragmento del loader de los repositorios del colaborador con la dirección de la cartera de Solana y la lista de nueve endpoints RPC públicos
Fuente: OpenSourceMalware, «Glassworm Hacks OVH Clouds CLI tool»

OpenSourceMalware presenta esa relación con cautela: según cuentan SecurityWeek y The Hacker News, reconoce que la conexión entre el compromiso de marzo y la sustitución de octubre es «our inference» (una inferencia suya). OVHcloud no menciona a GlassWorm en el aviso, aunque sí enlaza a una noticia sobre ese grupo en la sección de causa raíz. Lo que sí afirma la compañía es que el desarrollador instaló en su MacBook personal, el 20 de octubre de 2025, la extensión color-picker-universal 2.8.91, que esa instalación comprometió el equipo meses antes del incidente y que las credenciales robadas entonces sirvieron para sustituir las releases. El portátil corporativo del desarrollador «has not been compromised as far as we know» (no ha sido comprometido, hasta donde sabemos), según el aviso.

Para saber si un equipo ejecutó la compilación maliciosa, estos comandos comparan la huella del binario con las del aviso y buscan la carpeta que deja el stealer, sin ejecutar la CLI.

# Linux y macOS: huella MD5 del binario instalado (compárala con la tabla de IoC)
BIN="$(command -v ovhcloud)"
md5sum "$BIN" 2>/dev/null || md5 "$BIN"

# Origen de la compilación: una copia maliciosa muestra 5ead8ef y vcs.modified=true
go version -m "$BIN" | grep -E 'vcs\.revision|vcs\.modified|\+dirty'

# Carpetas que deja el stealer en el directorio temporal
ls -d "${TMPDIR:-/tmp}"/envchecker-* 2>/dev/null

En Windows, el equivalente es Get-FileHash con el algoritmo MD5 sobre ovhcloud.exe y una búsqueda de carpetas envchecker-* en la ruta de %TEMP%.

A quién afecta

A quien instalara o actualizara OVHcloud CLI en macOS (Intel o Apple Silicon), Linux x86_64 o arm64 y Windows x86_64 entre las 14:47 y las 16:21 del 19 de octubre, hora peninsular. Las cinco releases afectadas se publicaron entre el 14 de abril y el 16 de septiembre de 2026, de modo que quien las descargó antes de ese lunes tiene la copia buena. Los archivos de Linux i386, Windows i386, Windows arm64 y WebAssembly no se tocaron.

Las rutas de entrada, según The Hacker News y el propio aviso, son el script install.sh (hemos comprobado que la versión del tag v0.15.0 descarga el archivo de la release y no verifica ninguna huella), la descarga manual desde la página de releases, los pipelines de CI que bajan el archivo sin fijar su hash y el comando de actualización integrado en la CLI entre la v0.12.0 y la v0.14.0 en macOS y Linux. No afecta a quien instala con go install o compila desde el código fuente, porque el tag v0.15.0 sigue apuntando al commit original, ni a la imagen Docker ovhcom/ovhcloud-cli, cuya última publicación es del 21 de septiembre.

Con Homebrew hay una discrepancia entre fuentes. OpenSourceMalware y Help Net Security incluyen brew install entre los canales que entregaron el malware, mientras que The Hacker News sostiene que no, porque el cask fija el SHA-256 de cada archivo. El commit del tap de OVHcloud para la v0.15.0 contiene la huella 5c2beb56… del archivo Linux arm64, la original, así que una instalación con brew durante la ventana habría fallado la comprobación en lugar de instalar el binario sustituido. Quien use Homebrew puede comprobar su copia igualmente.

OVHcloud cifra las descargas en unas 250 y no las desglosa por país ni por plataforma. En el momento de escribir esta noticia, la mañana del 21 de octubre, ni INCIBE-CERT ni el CCN-CERT han publicado aviso sobre el incidente. El perfil de víctima lo marca el propio stealer: estaciones de trabajo de desarrolladores y de operaciones con credenciales de nube, de Kubernetes y de registros de paquetes en el disco, el mismo tipo de secreto que ya vimos convertirse en acceso a 173 tenants de Microsoft 365 a partir de una credencial robada a ConnectWise.

Qué hacer

  1. Comprueba cada equipo y runner de CI que haya instalado o actualizado la CLI el 19 de octubre con los comandos del apartado anterior. Si la huella MD5 coincide con la tabla, si el binario muestra el commit 5ead8ef o si existe una carpeta envchecker-* en el temporal, da el equipo por comprometido.
  2. Si hay indicios o no puedes descartarlos, rota desde otro equipo todos los secretos que el stealer busca: claves de la API de OVHcloud (archivo .ovh.conf y variables de entorno), credenciales de AWS, Google Cloud, Azure y DigitalOcean, config.json de Docker, kubeconfig, tokens de npm y Terraform, claves SSH, .netrc, tokens de Git y las sesiones de VS Code, Cursor, Continue, Cody, OpenCode, Hermes y Claude. Actualizar no revoca una clave que ya se copió.
  3. Borra el binario e instala la v0.16.0 desde la release inmutable. Verifica el archivo descargado con gh release verify-asset antes de ejecutarlo.
  4. Busca en el proxy, el firewall y el EDR conexiones a 45.32.148[.]174:443 y consultas a los endpoints RPC de Solana desde equipos que no tengan motivo para hablar con esa cadena de bloques.
  5. En los pipelines, fija el SHA-256 de cada archivo que descargues de una release y prefiere go install o la compilación desde el código fuente para herramientas en Go.
  6. Si gestionas los repositorios de tu organización en GitHub, activa la inmutabilidad de releases y la notificación privada de vulnerabilidades, dos ajustes que OVHcloud no tenía y que ha encendido tras el incidente.
  7. Si confirmas el robo de credenciales, notifícalo a INCIBE-CERT si eres empresa o ciudadano y al CCN-CERT si perteneces al sector público.

La verificación de la v0.16.0 se apoya en las atestaciones que GitHub genera para las releases inmutables y se hace con la CLI de GitHub.

# Verifica un archivo de la release v0.16.0 contra la atestación de GitHub
gh release verify-asset --repo ovh/ovhcloud-cli v0.16.0 ovhcloud-cli_Linux_x86_64.tar.gz

Si el comando devuelve error, no instales el archivo y descárgalo de nuevo desde la página de la release.

Análisis

Para quien administra servicios en OVHcloud, la CLI en sí tiene poco recorrido todavía y lo relevante es lo que busca el binario. La lista de rutas del aviso es un inventario de todo lo que un desarrollador deja en su disco para no tener que autenticarse cada vez: credenciales de tres nubes, el kubeconfig, el config.json de Docker, las claves SSH y las bases de datos de sesión de los asistentes de código. Quien ejecutó la copia sustituida tiene que asumir que todo eso salió de su equipo en el primer arranque, y la rotación ordenada de secretos es un trabajo de horas que conviene tener ensayado, como ya defendíamos al hablar de identidad y control de accesos en la nube.

El aviso oficial deja preguntas sin responder. OVHcloud no dice cuántas de las 250 descargas llegaron a ejecutarse, no explica cómo una cuenta personal comprometida en octubre de 2025 conservó permisos de escritura sobre las releases del proyecto durante un año y no detalla si las credenciales de GitHub estaban protegidas con doble factor. La compañía ha prometido un análisis posterior, y el detalle de que el loader de marzo y el stealer de octubre usen carteras de Solana distintas merece que alguien lo aclare antes de dar por cerrada la atribución a GlassWorm.

El fallo de fondo es de diseño. Las releases de GitHub nacieron mutables y la inmutabilidad es una opción que hay que activar por repositorio u organización, aunque esté disponible para todos desde octubre de 2025. Mientras no esté activada, cualquier cuenta con permiso de escritura puede cambiar un binario publicado hace seis meses sin dejar rastro en la interfaz, y el usuario que descarga desde la página oficial no tiene forma de notarlo salvo que compare huellas. En el caso de MALFEX en npm el vector era un paquete nuevo, aquí es un archivo viejo con la URL de siempre, y eso lo hace más difícil de detectar para quien confía en la procedencia.

Contexto

GlassWorm es el nombre con el que se conoce desde finales de 2025 una campaña contra desarrolladores que, según el análisis de CrowdStrike, lleva activa al menos desde principios de ese año. Empezó con extensiones troyanizadas para VS Code y sus derivados en el registro Open VSX, pasó a paquetes de npm y PyPI y, en marzo de 2026, a inyectar código en más de 300 repositorios de GitHub con credenciales robadas. Su sello es el uso de la blockchain de Solana como punto muerto: la dirección del servidor de mando se lee del campo memo de las transacciones de una cartera, de modo que no hay dominio que tumbar.

El 26 de mayo de 2026, CrowdStrike, Google y la Shadowserver Foundation desmantelaron de forma coordinada los cuatro canales de mando de la botnet. Lo ocurrido en OVHcloud encaja con una cuenta robada antes de esa operación y usada después, y es el mismo patrón que ya seguían las campañas de marzo: un desarrollador infectado por una extensión, sus credenciales de GitHub en manos del atacante y, meses más tarde, un cambio en un repositorio que nadie revisa. Quien mantenga proyectos públicos o privados en GitHub tiene en nuestra guía de herramientas y recursos DevSecOps un punto de partida para cerrar esa puerta.

Preguntas frecuentes

¿Basta con actualizar OVHcloud CLI a la v0.16.0?

No. La v0.16.0 sustituye el binario, pero el stealer actúa en el primer arranque y las credenciales copiadas ya están fuera del equipo. Si ejecutaste una copia descargada en la ventana del 19 de octubre, la prioridad es revocar y regenerar los secretos desde un equipo limpio, y solo después reinstalar la herramienta.

¿Cómo sé si descargué la versión maliciosa de OVHcloud CLI?

Calcula la huella MD5 del binario sin ejecutarlo y compárala con las cinco del aviso de OVHcloud. Si no conservas el archivo, revisa la fecha de instalación y busca carpetas envchecker-* en el directorio temporal, que el malware no borra. Un binario legítimo de la v0.15.0 muestra el commit 760fd72, y uno sustituido, el 5ead8ef con el sufijo +dirty.

¿Qué es la inmutabilidad de releases de GitHub?

Es un ajuste de repositorio u organización, disponible para todos los usuarios desde el 28 de octubre de 2025, que impide añadir, cambiar o borrar los archivos de una release después de publicarla y protege su tag. Las releases inmutables reciben además una atestación firmada en formato Sigstore que se puede comprobar con la CLI de GitHub. Solo afecta a las releases creadas después de activarlo.

¿Están afectadas las instalaciones hechas con Docker o con go install?

No, según OVHcloud y OpenSourceMalware. La imagen ovhcom/ovhcloud-cli no se modificó y el código fuente y el tag v0.15.0 siguen intactos, así que go install compila a partir del commit original. Lo mismo ocurre con quien compiló el proyecto por su cuenta.

Temas

No hay comentarios todavía