Neutron, nuestro motor de IA, obtuvo un 97.1% en el benchmark CyberGym de UC Berkeley. Más información

Análisis a fondo

Análisis a fondo

Archivos de versiones maliciosos de la CLI de OVHcloud roban secretos

Archivos sustituidos en cinco versiones de la CLI de OVHcloud distribuyeron una compilación que robaba secretos durante 94 minutos el 19 de octubre de 2026; rote todos los secretos e instale v0.16.0.

Resumen

  • El 19 de octubre de 2026, entre las 12:47 y las 14:21 UTC, un atacante que utilizaba la cuenta GitHub secuestrada de un colaborador sustituyó los archivos descargables de cinco versiones publicadas de la CLI de OVHcloud, v0.11.0 a v0.15.0, por una compilación que robaba secretos. Los archivos sustituidos estuvieron disponibles durante 94 minutos.
  • Quienes instalaron o actualizaron la CLI desde GitHub en esa ventana, en macOS x86_64 o arm64, Linux x86_64 o arm64 o Windows x86_64, mediante el script oficial, una descarga directa de versión, una descarga CI sin hash fijado o el comando de actualización de la propia CLI, recibieron la compilación sustituida. Homebrew, go install, Docker y las instalaciones anteriores a la ventana no estaban afectados.
  • El fundador de OVHcloud, Octave Klaba, afirmó que el binario busca secretos almacenados en el disco del usuario y que los afectados deberían cambiar todos los secretos guardados allí. No se ha analizado públicamente ninguna copia de los archivos sustituidos y OVHcloud no ha indicado cuántas copias se descargaron, por lo que se desconoce el número de víctimas.
  • Si instaló o actualizó en esa ventana, considere expuestos todos los secretos legibles desde ese equipo, rótelos desde otro equipo, elimine el binario e instale la versión inmutable v0.16.0, publicada esa misma tarde, verificándola con gh release verify-asset.

¿Estoy afectado?

Está afectado si se cumplen todas estas condiciones:

  • Instaló o actualizó la CLI de OVHcloud entre las 12:47 y las 14:21 UTC del 19 de octubre de 2026.
  • La instalación procedía de GitHub mediante una de las cuatro rutas siguientes.
  • Su plataforma era una de las cinco cuyos binarios se sustituyeron en cada versión: macOS x86_64 o arm64, Linux x86_64 o arm64 o Windows x86_64. Las compilaciones Linux i386, Windows i386, Windows arm64 y WebAssembly quedaron intactas en todas las versiones.

Las cuatro rutas de descarga afectadas:

  • El script oficial install.sh, que descarga el archivo de la última versión sin comprobar su hash.
  • Una descarga directa desde la página de GitHub de cualquiera de las cinco versiones sin verificación independiente.
  • Un trabajo CI o paso de compilación que descarga el archivo desde la URL de la versión sin un hash fijado.
  • El comando de actualización de la propia CLI, desde una instalación por script o manual en macOS o Linux. Descarga el archivo y sustituye el binario sin comprobar su hash.

No está afectado si se cumple cualquiera de estas condiciones:

  • Instaló con Homebrew. El cask vigente durante la ventana fijaba el SHA-256 original de cada archivo, y Homebrew rechaza descargas cuyo hash no coincida. Por tanto, una instalación o actualización con brew habría fallado en lugar de instalar el archivo sustituido. El historial del cask del tap no muestra cambios entre la actualización v0.15.0 del 16 de septiembre y la v0.16.0 del 19 de octubre. Algunos análisis iniciales incluían Homebrew como expuesto; los hashes fijados descartan esa ruta.
  • Utilizó go install o compiló desde el código fuente. La etiqueta v0.15.0 sigue apuntando a su commit de septiembre, 760fd72, y el árbol de código nunca se modificó.
  • Descargó la imagen Docker ovhcom/ovhcloud-cli. Su etiqueta latest se había publicado por última vez el 21 de septiembre, semanas antes de la sustitución, y no se había reconstruido.
  • Instaló antes de las 12:47 UTC del 19 de octubre y no actualizó durante la ventana, o solo descargó las compilaciones Linux o Windows i386, Windows arm64 o WebAssembly.
Versión Estado
v0.11.0 a v0.15.0, publicadas del 14 de abril al 16 de septiembre de 2026 Seis archivos por versión sustituidos durante la ventana: cinco binarios de plataforma y checksums.txt; Linux i386, Windows i386, Windows arm64 y WebAssembly intactos; OVHcloud eliminó los archivos sustituidos a las 14:21 UTC
v0.10.0, publicada el 2 de marzo de 2026 Limpia: los diez archivos originales intactos con sus marcas de tiempo originales
v0.16.0, publicada el 19 de octubre de 2026 a las 17:16 UTC Sustitución limpia e inmutable, publicada por la cuenta de servicio ovh-cds con una atestación de versión

¿Cómo lo corrijo?

Instale una versión limpia verificada. Para Linux x86_64, utilice la CLI de GitHub para descargar v0.16.0, verificar su atestación antes de extraerla e instalar el binario verificado:

gh release download v0.16.0 --repo ovh/ovhcloud-cli \
  --pattern 'ovhcloud-cli_Linux_x86_64.tar.gz' &&
gh release verify-asset v0.16.0 ovhcloud-cli_Linux_x86_64.tar.gz \
  --repo ovh/ovhcloud-cli &&
  tar xzf ovhcloud-cli_Linux_x86_64.tar.gz &&
  sudo install -m 0755 ovhcloud /usr/local/bin/ovhcloud

Para otras plataformas, seleccione el archivo correspondiente de la versión v0.16.0 y verifíquelo antes de extraerlo o ejecutarlo.

La versión v0.16.0 es inmutable, por lo que GitHub no permite cambiar sus archivos. Incluye una atestación de versión, un registro firmado de los archivos que comprueba el comando de verificación. En adelante, fije el SHA-256 del archivo en CI. Las rutas de descarga afectadas carecían de una comprobación independiente del hash para rechazar la sustitución. Un trabajo CI consumidor con hash fijado detectó el cambio.

¿Qué hace el código malicioso?

Según la propia descripción de OVHcloud, el binario sustituido roba secretos, fue construido desde una copia local fuera del pipeline de publicación del proyecto y no se ha conservado ni analizado públicamente ninguna copia.

Klaba afirmó que el binario busca secretos en el disco del usuario y calificó su calidad como mediocre pero funcional. OVHcloud no ha publicado qué rutas lee, dónde envía lo recopilado ni cuántas copias se descargaron, y eliminó los archivos sustituidos antes de que alguien los archivara. Por tanto, el comportamiento del payload solo se conoce por la descripción del proveedor.

Lo que demuestran los metadatos de compilación, según la salida de go version -m capturada por el informante antes de la eliminación, es cómo se construyó:

  • La línea del módulo indica v0.15.1-0.20261013083505-5ead8ef9b43d+dirty, una pseudoversión: el valor provisional que Go genera para una compilación desde un commit sin etiqueta, en este caso del 13 de octubre de 2026. Una publicación auténtica utiliza su etiqueta. La compilación limpia v0.16.0 de OVHcloud indica v0.16.0+dirty: el sufijo +dirty también aparece en compilaciones genuinas. El marcador distintivo aquí es la marca temporal de pseudoversión 0.20261013083505, junto con el commit y las opciones de compilación inesperados.
  • El commit registrado es 5ead8ef, no 760fd72, al que apunta la etiqueta v0.15.0. Es un árbol de la época v0.16 con nombre de archivo v0.15.0.
  • Aparece una línea -ldflags="-s -w". El pipeline del proyecto compila con una opción de versión que Go omite de las opciones registradas, por lo que una publicación auténtica no muestra ninguna línea -ldflags.
  • vcs.modified=true significa que el árbol de trabajo tenía cambios sin commit al compilarse, coherente con modificaciones aplicadas a una copia local. Esta opción por sí sola no muestra qué cambió ni demuestra que la compilación sea maliciosa.

¿Cómo ocurrió la sustitución?

La sustitución necesitó una cuenta de colaborador secuestrada con acceso de escritura y la inmutabilidad de versiones desactivada. La cuenta utilizó la API GitHub Releases para sustituir seis archivos en cada una de cinco versiones, subiendo checksums.txt al final para que los hashes publicados coincidieran con los binarios de reemplazo.

Los pasos, reconstruidos por OpenSourceMalware a partir de registros del servidor de GitHub y corroborados por la incidencia #300 del informante:

  1. El atacante poseía credenciales de HassenBF, un colaborador legítimo de OVH con escritura en ovhcloud-cli. Sus contribuciones públicas integradas están en el repositorio de documentación de OVHcloud. La cuenta llevaba meses comprometida: el 5 y 6 de marzo de 2026, cuatro repositorios personales recibieron pushes forzados con commits de punta modificados que añadían un cargador oculto, el primer uso de la cuenta por el atacante verificado por el servidor.
  2. Entre las 12:47 y aproximadamente las 13:12 UTC del 19 de octubre, mediante la API GitHub Releases normal, la cuenta eliminó y volvió a subir cinco archivos de plataforma y checksums.txt en v0.15.0. Después repitió la operación en v0.14.0, v0.13.0, v0.12.0 y v0.11.0, subiendo siempre checksums.txt al final para que los hashes publicados coincidieran con los nuevos binarios.
  3. No se publicó ninguna etiqueta ni se ejecutó ningún flujo GitHub Actions. El flujo de publicación solo se activa al publicar etiquetas, y la lista de ejecuciones no muestra ningún flujo entre el 16 de octubre y la publicación de la etiqueta v0.16.0 a las 16:00 UTC del 19 de octubre. El pipeline del proyecto nunca se tocó; el atacante subió directamente a las versiones existentes.
  4. Cada ruta de instalación afectada descargó el nuevo archivo desde la misma URL de versión, sin comprobar el hash en ningún punto: el script nunca lo ha comprobado, el comando de actualización tampoco y el CI sin hash fijado descargó lo que hubiera.
  5. Un trabajo CI consumidor cuyo propietario había fijado el SHA-256 del archivo Linux arm64 falló a las 13:50 UTC. Su propietario ejecutó go version -m, encontró la compilación ajena al pipeline y abrió una incidencia pública porque el repositorio no tenía canal privado de informes. OVHcloud eliminó los archivos sustituidos a las 14:21 UTC y publicó la v0.16.0 inmutable a las 17:16 UTC.
flowchart LR A["Cuenta de colaborador secuestrada
con acceso de escritura"] --> B["La API Releases sustituye seis archivos
en cinco versiones publicadas"] B --> C["checksums.txt sustituido al final,
los hashes publicados coinciden"] C --> D["Las instalaciones descargan la misma URL
sin comprobar el hash en ningún punto"] D --> E["La compilación que roba secretos
se ejecuta en el equipo del desarrollador"] C --> F["Otro trabajo CI rechaza la descarga:
el SHA-256 fijado no coincide"] style D fill:#f8d7da

La brecha está en D: ninguna de las cuatro rutas afectadas verificó de forma independiente el archivo descargado antes de ejecutarlo. La comprobación separada de SHA-256 fijado en F falló y detectó la sustitución antes de que ese trabajo CI pudiera ejecutar el reemplazo.

¿Qué puede hacer un atacante?

Un ladrón de secretos que se ejecuta como el usuario puede leer y copiar los secretos disponibles para esa cuenta. Considere expuestos los siguientes, siguiendo la recomendación de OVHcloud de cambiar todos los secretos del equipo afectado:

  • Credenciales OVHcloud: credenciales de API en ~/.ovh.conf y variables de entorno.
  • Otros secretos legibles: claves SSH, archivos .npmrc, .netrc, .pypirc, .env y credenciales de nube o CI.

Estas son las credenciales que debe inventariar y rotar; el payload eliminado no se ha analizado públicamente para establecer su lista exacta de objetivos.

Las condiciones que necesita el ataque:

  • Una instalación o actualización durante la ventana de 94 minutos mediante una de las cuatro rutas afectadas, en una de las cinco compilaciones de plataforma sustituidas.
  • Nada más. Ninguna interacción aparte del comando normal de instalación, ningún compromiso del código fuente o pipeline de OVHcloud y ninguna acción de la víctima más allá de ejecutar la herramienta que pretendía utilizar.

¿Qué debo hacer si lo instalé?

Si ejecutó una compilación sustituida, o no puede demostrar que no lo hizo, siga las indicaciones de OVHcloud con la aportación de OpenSourceMalware:

  1. Considere expuestos todos los secretos legibles desde ese equipo y rótelos desde otro, porque el binario sustituido podría seguir ejecutándose en el afectado. La rotación va primero: actualizar el binario sustituye el programa, pero no revoca una clave ya copiada.
  2. Elimine el binario e instale v0.16.0 o posterior, la versión inmutable publicada esa misma tarde.
  3. Verifique el nuevo archivo con gh release verify-asset v0.16.0 FILE --repo ovh/ovhcloud-cli y fije el SHA-256 en cualquier trabajo CI o Dockerfile que lo descargue, el control cuya ausencia abrió la ruta.

¿Cómo compruebo si he sufrido una intrusión?

Compruebe el binario sin ejecutarlo. Tres marcadores distinguen la compilación sustituida. Los matices importan porque aconsejar que cualquier compilación +dirty o con líneas vcs es maliciosa señalaría las propias versiones genuinas de OVHcloud, que indican v0.16.0+dirty y vcs.modified=true:

go version -m ./ovhcloud
  • La línea del módulo es una pseudoversión, v0.15.1-0.20261013083505-5ead8ef9b43d+dirty, en lugar de una etiqueta como v0.15.0 o v0.16.0.
  • El commit registrado es 5ead8ef en lugar del commit de la etiqueta, 760fd72 para v0.15.0.
  • Aparece una línea -ldflags="-s -w"; las compilaciones auténticas de OVHcloud no muestran ninguna línea -ldflags.

En salidas ya existentes de ovhcloud version, una v0.16.0 genuina indica v0.16.0. El valor predeterminado del código es undefined cuando se omite la opción de versión; ese es el valor esperado de una compilación por lo demás intacta con las opciones registradas. No es una observación confirmada del payload eliminado. Utilice las comprobaciones estáticas anteriores en lugar de ejecutar un binario sospechoso.

Para el único archivo con un par de hashes publicado, compare directamente:

  • v0.15.0 ovhcloud-cli_Linux_arm64.tar.gz, sustituido: 3833daffcaaaab27e4e0e0833240ffcb1df8df648f4ec0bc4a75c176e28933cb
  • v0.15.0 ovhcloud-cli_Linux_arm64.tar.gz, original: 5c2beb56e6d83a4b426565a1557791ef759316abcc4effb38dd627c90aeb80e0

Los indicadores publicados por OpenSourceMalware para la campaña de compromiso de cuentas son distintos del binario CLI, porque no se conservó ninguna copia de este:

  • Cuenta GitHub secuestrada: HassenBF (ID 4911006).
  • Cargador: preinstall.js, SHA-256 43df42fd79f6f81e530892b54634598770d6e496796a863c596e616bcb3fec70.
  • Script de ciclo de vida: entradas "preinstall": "node preinstall.js" en package.json.
  • Cartera Solana de buzón encubierto: BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC.
  • Archivo de limitación: ~/init.json en el directorio personal de macOS.

Cronología

Todas las horas en UTC, según los registros del servidor de GitHub publicados por OpenSourceMalware, la incidencia #300 del informante y los registros de versiones.

  • 2026-03-05 y 03-06: cuatro repositorios personales de HassenBF reciben pushes forzados con commits de punta modificados y cargadores ocultos, el primer uso de la cuenta por el atacante verificado por el servidor.
  • 2026-05-25 a 09-07: la cuenta sigue incorporando pull requests normales en el repositorio de documentación de OVHcloud.
  • 2026-10-13 08:35: el commit 5ead8ef se integra en main; el binario malicioso se construye después desde ese árbol con cambios adicionales sin commit (vcs.modified=true).
  • 2026-10-19 12:47: llegan los primeros archivos sustituidos a v0.15.0.
  • 12:57: se sustituye checksums.txt de v0.15.0 para que coincidan los hashes publicados.
  • 13:01 a 13:12: se sustituyen v0.14.0, v0.13.0 y, en la misma pasada, v0.12.0 y v0.11.0; termina el reemplazo.
  • 13:50: el propietario del CI cuya comprobación SHA-256 falló abre la incidencia #300.
  • 14:21: OVHcloud elimina todos los archivos reemplazados en las cinco versiones.
  • 16:00: publicar la etiqueta v0.16.0 inicia los flujos de compilación y publicación.
  • 17:16: la cuenta de servicio ovh-cds publica v0.16.0, inmutable y con atestación; Klaba publica la alerta en X.
  • 2026-10-20: OVHcloud afirma que las primeras comprobaciones no muestran otros repositorios afectados y promete un análisis posterior al incidente.
  • 2026-10-26: este artículo.

Preguntas frecuentes

¿Estaba afectado Homebrew?

No. El cask vigente durante la ventana fijaba el SHA-256 original de cada archivo, y Homebrew rechaza una descarga cuyo hash no coincide; por tanto, la instalación o actualización habría fallado visiblemente en lugar de instalar el archivo sustituido. Los primeros análisis incluyeron Homebrew entre las rutas expuestas, pero el historial de commits del tap muestra que nada cambió entre los cask v0.15.0 y v0.16.0.

¿Se comprometieron el código fuente o el pipeline de compilación?

No. La etiqueta v0.15.0 sigue apuntando al commit de septiembre, el árbol de código nunca se modificó y ningún flujo GitHub Actions se ejecutó durante el reemplazo: la lista está vacía entre el 16 de octubre y la publicación de la etiqueta v0.16.0. El atacante subió archivos a versiones existentes mediante la API Releases con el token de una cuenta de colaborador. La sustitución fue posible porque la inmutabilidad estaba desactivada.

¿Por qué importaba la configuración de versiones inmutables?

Cualquiera con acceso de escritura al repositorio puede eliminar y volver a subir archivos adjuntos a una versión sin cambiar la URL de descarga, salvo que esté activada la funcionalidad de versiones inmutables de GitHub. OVHcloud no la había activado; la funcionalidad, disponible de forma general desde octubre de 2025, bloquea los archivos y la etiqueta de una versión, pero solo protege las creadas después de activarla. Ahora está activada, por eso v0.16.0 no puede modificarse de la misma forma.

¿Cómo sé que v0.16.0 está limpia?

La publicó la cuenta de servicio ovh-cds de OVHcloud, no una cuenta personal; está marcada como inmutable, de modo que sus archivos no pueden sustituirse, e incluye una atestación que puede comprobar con gh release verify-asset v0.16.0 FILE --repo ovh/ovhcloud-cli, siguiendo el flujo de verificación publicado por GitHub.

¿Se comprometió realmente a alguien?

Se desconoce. OVHcloud no ha indicado cuántas copias de los archivos sustituidos se descargaron durante los 94 minutos y no se conservó ninguna, por lo que no hay recuento de víctimas ni análisis del payload. Para cualquiera que utilizara una ruta afectada durante la ventana, la postura segura es rotar independientemente de la evidencia.

¿Es la campaña GlassWorm?

El vínculo de la cuenta es real; la atribución no está demostrada. Los repositorios propios de la cuenta secuestrada recibieron pushes forzados en marzo con cargadores vinculados por su cartera Solana de buzón encubierto a la campaña ForceMemo de GlassWorm. Que el mismo actor utilizara la cuenta en octubre es, en palabras de OpenSourceMalware, una inferencia: nada del binario de octubre se ha vinculado a GlassWorm porque no se conservó ninguna copia.

Encuentre descargas sin hash fijado antes de la próxima sustitución

Empiece por la guía de escaneo de código fuente de Ostorlab para revisar riesgos del repositorio. Para OVHcloud, inspeccione las configuraciones CI y Dockerfiles en busca de descargas de versiones sin hash fijado y compruebe binarios conservados con go version -m buscando la pseudoversión v0.15.1-0.20261013083505-5ead8ef9b43d+dirty y la línea -ldflags="-s -w". Estas comprobaciones manuales no suponen que un escáner disponga de una firma específica del incidente.

Referencias

  • The Hacker News, «Atacantes secuestran cinco versiones de la CLI de OVHcloud para distribuir malware que roba secretos», 20 de octubre de 2026, con rutas de exposición, verificación del tap Homebrew, marcadores de detección y matices sobre compilaciones +dirty: https://thehackernews.com/2026/10/hackers-hijack-five-ovhcloud-cli.html (consultado el 26 de octubre de 2026)
  • OpenSourceMalware, «Glassworm compromete la herramienta CLI de OVH Clouds», 19 de octubre de 2026, cronología del servidor, tabla de debilidades, indicadores de campaña y límites de atribución: https://opensourcemalware.com/blog/glassworm-hacks-ovh-clouds-cli-tool (consultado el 26 de octubre de 2026)
  • Incidencia #300, captura de la sustitución, salida go version -m y par de hashes del informante, abierta a las 13:50 UTC del 19 de octubre de 2026: https://github.com/ovh/ovhcloud-cli/issues/300 (consultado el 26 de octubre de 2026)
  • Versión limpia e inmutable v0.16.0, publicada a las 17:16 UTC del 19 de octubre de 2026, con lista de archivos y registro de cambios: https://github.com/ovh/ovhcloud-cli/releases/tag/v0.16.0 (consultado el 26 de octubre de 2026)
  • Script de instalación de v0.15.0, que descarga desde la URL de versión sin comprobar hashes: https://github.com/ovh/ovhcloud-cli/blob/v0.15.0/install.sh (consultado el 26 de octubre de 2026)
  • Código de autoactualización de la CLI en v0.15.0, que descarga el archivo y sustituye el binario sin comprobar hashes: https://github.com/ovh/ovhcloud-cli/blob/v0.15.0/internal/upgrade/install.go (consultado el 26 de octubre de 2026)
  • Documentación de versiones inmutables de GitHub y entrada de disponibilidad general del 28 de octubre de 2025: https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases y https://github.blog/changelog/2025-10-28-immutable-releases-are-now-generally-available/ (consultado el 26 de octubre de 2026)
  • Flujo de verificación de archivos de versiones de GitHub: https://docs.github.com/en/code-security/how-tos/secure-your-supply-chain/secure-your-dependencies/verify-release-integrity (consultado el 26 de octubre de 2026)
  • Commit del cask del tap Homebrew vigente durante la ventana, que fija el SHA-256 original: https://github.com/ovh/homebrew-tap/commit/b70a654 (referenciado mediante The Hacker News, 26 de octubre de 2026)
  • Repositorio ovh/ovhcloud-cli, CLI oficial para gestionar servicios OVHcloud, 218 estrellas a fecha del 26 de octubre de 2026: https://github.com/ovh/ovhcloud-cli y https://api.github.com/repos/ovh/ovhcloud-cli (consultado el 26 de octubre de 2026)
  • Recuento de descargas de archivos de la versión limpia v0.16.0, 2.053 en la semana hasta el 26 de octubre de 2026: https://api.github.com/repos/ovh/ovhcloud-cli/releases/tags/v0.16.0 (consultado el 26 de octubre de 2026)
  • Declaraciones de Klaba del 19 de octubre en X, citadas por OpenSourceMalware y next.ink: https://next.ink/262824/le-client-en-ligne-de-commande-dovhcloud-compromis-par-un-pirate-sur-github/ (referenciado mediante The Hacker News, 26 de octubre de 2026)