Skip to main content

«Ha aparecido un Mini Shai-Hulud»: un malware de robo de información basado en Bun ataca los paquetes npm @cap-js y mbt de SAP

Escrito por

29 de abril de 2026

0 minutos de lectura

El 29 de abril de 2026, atacantes publicaron versiones maliciosas de cuatro paquetes npm del ecosistema de desarrollo de SAP: mbt, @cap-js/db-service, @cap-js/sqlite y @cap-js/postgres. Cada versión comprometida incluye un hook preinstall que descarga el runtime de JavaScript Bun desde GitHub Releases y lo usa para ejecutar un ladrón de credenciales ofuscado de aproximadamente 11,6 MB.

El payload se identifica con una descripción codificada: «A Mini Shai-Hulud has Appeared». Esta aparece en tiempo real en los resultados públicos de búsqueda de GitHub, mientras las máquinas de desarrolladores comprometidas crean repositorios de entrega en las cuentas de sus propios usuarios. La campaña reutiliza el nombre Shai-Hulud (los repositorios de entrega están etiquetados con ese nombre) e incluye código funcional para propagarse por npm, según la desofuscación completa de StepSecurity. A la fecha de publicación, solo se habían observado en circulación los cuatro paquetes comprometidos originalmente; a continuación se detallan el análisis técnico y la cuenta npm comprometida que permitió las publicaciones iniciales.

Snyk publicó avisos para las cuatro versiones comprometidas. Las versiones afectadas aparecen señaladas con snyk test y en la página de la base de datos de seguridad de Snyk de cada paquete.

Paquetes afectados y avisos de Snyk

Paquete

Versión comprometida

Aviso de Snyk

Descargas semanales aprox.

mbt

1.2.48

~52.000

@cap-js/db-service

2.10.1

~260.000

@cap-js/sqlite

2.2.2

~250.000

@cap-js/postgres

2.2.2

~10.000

Cantidad semanal de descargas según la API pública de descargas del registro npm para la semana anterior al ataque (del 22 al 28 de abril de 2026). Los cuatro paquetes forman parte de la cadena de herramientas SAP Cloud Application Programming Model. mbt es la herramienta Cloud MTA Build Tool distribuida por npm, que se usa para crear archivos de despliegue para aplicaciones en la nube de SAP; los paquetes @cap-js/* proporcionan servicios de base de datos para aplicaciones CAP.

Las versiones maliciosas se publicaron en un breve período el 29 de abril de 2026, todas en UTC. Las marcas de tiempo se verificaron directamente en registry.npmjs.org y la API de GitHub:

  • 09:55:25: se publicó mbt@1.2.48 desde la cuenta npm cloudmtabot.

  • 10:01:07: aparece en GitHub el primer repositorio de entrega de una víctima (gruposbftechrecruiter/siridar-navigator-935, según las marcas de tiempo de la API de GitHub).

  • 11:25:47: se publicó @cap-js/sqlite@2.2.2.

  • 12:03 to 12:04: StepSecurity presenta avisos de divulgación en cap-js/cds-dbs#1588 y SAP/cloud-mta-build-tool#1224. A las 14:02, longieirl presenta una tercera divulgación independiente, SAP/open-ux-tools#4616.

  • 12:14:00: se publicaron @cap-js/postgres@2.2.2 y @cap-js/db-service@2.10.1.

  • 13:31: el mantenedor de cap-js chgeo responde: «Gracias por avisarnos. Vamos a limpiar los paquetes con la máxima prioridad e investigar las causas raíz».

  • 13:46: SAP publica versiones limpias posteriores al incidente mediante el publicador de confianza OIDC de GitHub Actions cap-npm: @cap-js/db-service@2.11.0, @cap-js/sqlite@2.4.0, @cap-js/postgres@2.3.0 (junto con la actualización coordinada @cap-js/hana@2.8.0).

  • 14:02:50: el ingeniero de SAP patricebender presenta el PR #1592 de cap-js/cds-dbs, que exige aprobación manual en un entorno antes de publicar en npm; incluye la declaración textual sobre la causa raíz citada arriba.

  • 14:24: kbarnold responde en calidad de colaborador de cloud-mta-build-tool: «Gracias por el informe. Estamos trabajando en ello con máxima prioridad».

Poco después de su detección, se retiró de npm @cap-js/sqlite@2.2.2. Las demás versiones maliciosas incluyen mensajes de desuso en npm: mbt@1.2.48 está marcada con «SEGURIDAD: esta versión contiene código malicioso. No la uses», mientras que las versiones maliciosas de @cap-js/* muestran «NO USAR. Esta versión contiene contenido desconocido». Es importante destacar que, al momento de redactar este artículo, mbt@1.2.48 seguía siendo la etiqueta de distribución latest para mbt y aún no se había publicado una versión corregida de mbt. Esto significa que un npm install mbt sin especificar una versión sigue instalando el archivo tar malicioso. Al publicarse este artículo, ninguno de los cuatro paquetes tenía asignado un CVE, GHSA ni registro OSV; las únicas fuentes públicas oficiales son las cuatro publicaciones de proveedores citadas en este artículo y los tres avisos de divulgación de GitHub.

Por qué se llama «Mini» Shai-Hulud (y qué es realmente diferente)

La convención de nombres Shai-Hulud ya ha aparecido dos veces en incidentes de la cadena de suministro de npm. La campaña original Shai-Hulud, de septiembre de 2025, afectó a @ctrl/tinycolor, ngx-bootstrap, ng2-file-upload y muchos otros paquetes dependientes (el informe de vulnerabilidad de día cero de Snyk documentó el incidente mientras se desarrollaba). La siguiente ola, SHA1-Hulud, de noviembre de 2025, se extendió a más de 600 paquetes distintos, con versiones de Zapier, PostHog y Postman. El equipo Securelist de Kaspersky publicó análisis técnicos independientes de ambas olas anteriores (nombre de detección: HEUR:Worm.Script.Shulud.gen) en securelist.com/shai-hulud-worm-infects-500-npm-packages y securelist.com/shai-hulud-2-0.

A Mini Shai-Hulud Has Appeared": Bun-Based Stealer Hits SAP @cap-js and mbt npm Packages

Ataque Shai-Hulud a npm: cómo corregirlo con Snyk (breve guía para identificar y corregir dependencias afectadas por Shai-Hulud en tus proyectos con la CLI y las páginas de asesoramiento de Snyk).

Ambas campañas anteriores mostraron comportamiento de gusano: el payload robaba el token npm de la víctima y luego lo usaba para publicarse en todos los demás paquetes a los que ese token tenía acceso de escritura. La atención pública ha seguido la misma tendencia: el artículo de Wikipedia sobre el gusano de arena de Dune llegó a 2.772 visitas durante la divulgación de SHA1-Hulud en noviembre de 2025 (la cifra diaria más alta en un conjunto de datos de 16 meses, aproximadamente cuatro veces el promedio del artículo), y el artículo más general de Wikipedia sobre «ataques a la cadena de suministro» alcanzó su promedio mensual más alto registrado en abril de 2026, el mes de Mini Shai-Hulud (310 visitas al día, según la API REST de Wikimedia).

La campaña del 29 de abril reutiliza la marca Shai-Hulud (los repositorios dead-drop tienen nombres basados en la cadena de descripción), pero las pruebas públicas disponibles hasta ahora apuntan a un conjunto más acotado de comportamientos:

  • Robo de credenciales: observado y documentado por varios investigadores.

  • Inyección de persistencia en las configuraciones de herramientas para desarrolladores: un método novedoso que se detalla más adelante.

  • Autopublicación autónoma en npm: el código existe y funciona, según la desofuscación estática de StepSecurity. El payload recopila tokens de npm con la expresión regular /npm_[A-Za-z0-9]{36,}/g, valida cada uno en registry.npmjs.org/-/npm/v1/tokens (filtrando por bypass_2fa: true y permisos de escritura a nivel de organización), enumera los paquetes accesibles, modifica setup.mjs y execution.js en una copia del archivo tar y publica mediante una solicitud directa PUT al registro de npm, sin ejecutar la CLI de npm. Al publicarse este artículo, no se había observado en circulación ningún quinto paquete fuera de los cuatro originales que contuviera el payload malicioso. Sin embargo, la capacidad del gusano está comprobada empíricamente, no es una inferencia.

  • Secuestro de la canalización de CI como vector de acceso: la declaración oficial de SAP en el PR #1592 de patricebender en cap-js/cds-dbs (presentado ese mismo día a las 14:02 UTC) dice: «El 29 de abril de 2026, un ataque a la cadena de suministro comprometió el repositorio: un actor no autorizado subió commits maliciosos que secuestraron el flujo de publicación y activaron publicaciones no autorizadas en npm. El atacante pudo publicar paquetes comprometidos porque el flujo tenía permisos de publicación y no requería aprobación manual». La solución es exigir una revisión del entorno antes de publicar en npm. Según los datos del registro npm, las cuatro versiones maliciosas se publicaron desde la cuenta cloudmtabot (el mantenedor legítimo de mbt); las versiones limpias de SAP posteriores al incidente, publicadas a las 13:46 UTC, se publicaron mediante el publicador de confianza OIDC de GitHub Actions cap-npm, no desde cloudmtabot. Desde entonces, npm suspendió la cuenta cloudmtabot. El compromiso de las credenciales de los mantenedores es un punto de entrada recurrente en este tipo de incidentes, pero la declaración de SAP señala específicamente que la falta de aprobación en el flujo fue la causa raíz estructural.

El robo de credenciales permite la autorreplicación en npm, pero la actividad observada de inmediato consiste en exfiltración y un nuevo mecanismo de persistencia. Las prioridades defensivas (auditoría del archivo de bloqueo, rotación de credenciales y políticas para scripts del ciclo de vida) son las mismas en ambos casos.

Cómo funciona el ataque

El patrón del ataque es el mismo en los cuatro paquetes: el archivo tar malicioso conserva intactos los archivos legítimos del paquete (por lo que la CLI sigue funcionando después de la instalación) y agrega dos archivos nuevos: setup.mjs (un cargador de Bun de 4,5 KB en texto plano, idéntico byte por byte en los cuatro paquetes) y execution.js (un payload ofuscado de exactamente 11.678.349 bytes, con hashes distintos entre mbt y los paquetes @cap-js/*). Solo en el caso de mbt, el package.json malicioso también agrega tres dependencias (axios, tar y unzip-stream) que no aparecen en la versión limpia anterior; los tres paquetes cap-js solo agregaron el hook preinstall a su package.json existente.

Descargar un cargador pequeño durante la instalación y usarlo para obtener un runtime y un payload mucho más grandes es una técnica que Snyk ha observado en otros casos este año, incluido el axios, en el que el hook de instalación buscaba un binario nativo distribuido mediante una dependencia aparte.

En mbt, la diferencia entre 1.2.47 (limpia) y 1.2.48 (maliciosa) es la siguiente:

// 1.2.47: no scripts block
// 1.2.48:
{
  "scripts": {
    "preinstall": "node setup.mjs"
  },
  "dependencies": {
    "axios": "^1.13.5",
    "tar": "^7.5.7",
    "unzip-stream": "^0.3.4"
  }
}

preinstall se ejecuta antes de que npm muestre cualquier salida al usuario y antes de que pueda intervenir una política condicional --ignore-scripts, si no se especifica la opción. El hook ejecuta setup.mjs, que:

  1. Detecta la plataforma y la arquitectura (incluida la detección de Alpine/musl en Linux).

  2. Comprueba si bun ya está en PATH mediante hasCommand("bun"). Si lo encuentra, omite la descarga y usa el binario existente. De lo contrario, descarga Bun 1.3.13 desde GitHub Releases (siguiendo las redirecciones HTTP sin validar el destino, según el análisis de Socket).

  3. Si se descargó el binario de Bun, lo extrae en un directorio temporal.

  4. Ejecuta bun execution.js para correr el payload ofuscado.

Una vez que se ejecuta bun execution.js, el payload pasa por dos capas de ofuscación: una rotación de tabla de cadenas al estilo de obfuscator.io (48.370 entradas decodificadas con un alfabeto base64 no estándar y protegidas por una suma de verificación de inicio) y un cifrado personalizado que StepSecurity denominó «ctf-scramble-v2», con una clave maestra derivada de PBKDF2. Ambas capas se recuperaron por completo mediante análisis estático. El código de ejecución desofuscado es JavaScript que corre en Bun (no contiene WASM integrado ni código nativo; el payload usa API nativas de Bun como Bun.gunzipSync() y Bun.main).

La desofuscación estática de StepSecurity describe los siguientes comportamientos del payload:

  • Recopila credenciales locales, tokens de GitHub y npm, secretos de GitHub Actions, secretos en la nube de AWS, Azure, GCP y Kubernetes, tokens de CLI de administradores de contraseñas (1Password, Bitwarden y LastPass), ~/.claude.json y configuraciones de servidores MCP, variables de entorno que coinciden con los patrones KEY/TOKEN/SECRET/PASSWORD y claves de billeteras de criptomonedas presentes en el equipo. El payload también consulta el servicio de metadatos de instancias de AWS (169.254.169.254) cuando está disponible.

  • En los ejecutores de CI de Linux, inicia un proceso secundario de Python que lee /proc/{pid}/mem del proceso Runner.Worker de GitHub Actions para extraer secretos en texto sin formato directamente de la memoria del ejecutor.

  • En Windows, invoca PowerShell con -ExecutionPolicy Bypass.

  • Serializa los datos robados como JSON, los comprime con gzip, los cifra con AES-256-GCM (clave de 32 bytes, IV de 12 bytes) y protege la clave AES con RSA-OAEP-SHA256 mediante una clave pública RSA-4096 incrustada (almacenada como PEM comprimido con gzip y codificado en base64 en el desplazamiento de archivo 9,429,992 de execution.js, y descomprimida en tiempo de ejecución mediante Bun.gunzipSync()). Esto significa que los defensores que descubran el repositorio de depósito pueden ver que se robaron datos, pero no pueden determinar qué se robó. En la práctica, se debe considerar expuesta toda credencial a la que el proceso haya podido acceder.

  • Crea un repositorio público en la cuenta de GitHub de la víctima, con un nombre formado por caracteres aleatorios y la descripción «A Mini Shai-Hulud has Appeared», y guarda el texto cifrado como depósito.

  • Comprueba la configuración regional del sistema mediante la API de JavaScript Intl y las variables de entorno POSIX (LC_ALL, LC_MESSAGES, LANGUAGE, LANG). Si detecta una configuración regional rusa (ru), la carga útil registra "Exiting as russian language detected!" y termina. Las comprobaciones que excluyen regiones de la CEI coinciden con el comportamiento documentado de las operaciones de ciberdelincuencia en esas regiones.

El mecanismo de persistencia

Independientemente de que la campaña se clasifique como un gusano, el mecanismo de persistencia es el elemento más novedoso documentado en los informes públicos.

Según StepSecurity, la carga útil usa tres mecanismos de persistencia y reejecución:

  • Inyección de configuración de herramientas para desarrolladores. En cada repositorio de GitHub al que pueda escribir el token robado, la carga útil agrega un archivo .claude/settings.json que usa el hook Claude Code SessionStart para volver a ejecutar la carga útil cada vez que un desarrollador inicia una sesión de Claude Code, y un archivo .vscode/tasks.json con "runOn": "folderOpen" que se activa al abrir el proyecto en VS Code. Estos archivos inyectados se confirman con la identidad claude@users.noreply.github.com y el mensaje "chore: update dependencies", que puede parecer una confirmación rutinaria de automatización durante la revisión de un PR.

  • Inyección de flujos de trabajo de GitHub Actions. Cuando el token robado tiene el alcance workflow, la carga útil crea una rama con un nombre parecido a uno legítimo: dependabout/github_actions/format/setup-formatter (observa que falta una t) y confirma .github/workflows/format-check.yml haciéndose pasar por la cuenta de servicio de Dependabot (dependabot[bot]@users.noreply.github.com, con el mensaje de confirmación "Add formatter workflow"). El flujo de trabajo inyectado usa ${{ toJSON(secrets) }} para volcar todos los secretos del repositorio en un artefacto de compilación llamado format-results.txt.

  • Ejecución como daemon en las computadoras de los desarrolladores. En equipos que no son de CI, la carga útil se bifurca como un proceso en segundo plano independiente, marcado con la variable de entorno __DAEMONIZED=1; luego, el proceso principal termina correctamente, por lo que npm install vuelve al usuario sin mostrar errores. El proceso secundario continúa ejecutándose sin una relación clara con su proceso de origen.

Esto amplía el conjunto de vectores de persistencia durante la instalación observados en campañas de ataques a la cadena de suministro de npm para incluir archivos de configuración de agentes de programación con IA, junto con hooks del ciclo de vida de package.json, flujos de trabajo de CI y manifiestos de complementos de IDE.

La superficie de ataque de configuración de agentes de IA tiene antecedentes documentados; no es algo que aparezca por primera vez. El informe VSCode #309406 de Microsoft sobre el vector tasks.json runOn: folderOpen se presentó dieciséis días antes y se cerró como «By Design» (se considera que Workspace Trust es una mitigación suficiente, aunque la comprobación de confianza no cubre las confirmaciones realizadas en repositorios que ya son de confianza). El informe claude-code #49778 de Anthropic sobre el hook SessionStart se presentó doce días antes y sigue abierto, sin respuesta de Anthropic; en él se cita un precedente real en la auditoría de la cadena de suministro de Cozempic. El compromiso de agentes de IA de Trivy (CVE-2026-28353) de marzo de 2026 fue más lejos: usó tokens robados para publicar una extensión de VS Code armada que apuntaba a cinco agentes de programación con IA distintos. Snyk cubrió este mismo cruce por separado en el artículo sobre Clinejection. Mini Shai-Hulud es otro ejemplo de este patrón, no el primero.

Indicadores de compromiso

Esta lista resume los informes públicos de StepSecurity, Aikido, Socket y SafeDep. Consulta esos informes para ver la lista completa de indicadores de compromiso (IOC) y los detalles forenses. Cada versión maliciosa se puede consultar como registro inmutable en el registro de npm: registry.npmjs.org/mbt/1.2.48, registry.npmjs.org/@cap-js/sqlite/2.2.2, registry.npmjs.org/@cap-js/postgres/2.2.2 y registry.npmjs.org/@cap-js/db-service/2.10.1; en cada registro se conservan la marca de tiempo de publicación y la huella "preinstall": "node setup.mjs".

Compromised npm artifacts
  mbt@1.2.48                       shasum 0af7415d65753f6aede8c9c0f39be478666b9c12
  @cap-js/db-service@2.10.1        shasum 4b04304f6d51392e3f43856c94ca95800518a694
  @cap-js/sqlite@2.2.2             shasum 7b6a28e92149637e5d7c7f4a2d3e54acd507c929
  @cap-js/postgres@2.2.2           shasum e80824a19f48d778a746571bb15279b5679fd61c

Compromised npm publisher account
  cloudmtabot (used to publish all four malicious versions)

Files added to the compromised tarballs
  setup.mjs       ~4.5 KB plaintext Bun loader, byte-identical
                   across all four packages
  execution.js    11,678,349 bytes obfuscated payload, hash
                   differs per package

File hashes (SHA-256, per StepSecurity)
  setup.mjs (all packages)
    4066781fa830224c8bbcc3aa005a396657f9c8f9016f9a64ad44a9d7f5f45e34
  execution.js (mbt@1.2.48)
    80a3d2877813968ef847ae73b5eeeb70b9435254e74d7f07d8cf4057f0a710ac
  execution.js (@cap-js/sqlite@2.2.2)
    6f933d00b7d05678eb43c90963a80b8947c4ae6830182f89df31da9f568fea95
  Embedded /proc/mem dumper
    29ac906c8bd801dfe1cb39596197df49f80fff2270b3e7fbab52278c24e4f1a7

In-payload indicators (recovered by StepSecurity static analysis)
  Custom cipher salt              ctf-scramble-v2
  PBKDF2 input key                5012caa5847ae9261dfa16f91417042f367d6bed149c3b8af7a50b203a093007
  Derived master key              fd4b0f07b27e8f41bc70b8e2b79d168fb3fe80d7e0b37f43c506136a3418b44d
  CIS evasion log string          Exiting as russian language detected!
  Daemonization env var           __DAEMONIZED
  GitHub PAT regex                /gh[op]_[A-Za-z0-9]{36}/g
  npm token regex                 /npm_[A-Za-z0-9]{36,}/g

Network and runtime indicators
  - Outbound request to github.com/oven-sh/bun/releases/download/bun-v1.3.13/{asset}.zip
    where {asset} is one of:
      bun-linux-aarch64
      bun-linux-x64-baseline
      bun-linux-x64-musl-baseline
      bun-darwin-aarch64
      bun-darwin-x64
      bun-windows-aarch64
      bun-windows-x64-baseline
    (skipped if `bun` is already on PATH)
  - Process chain during install:
    node setup.mjs -> bun execution.js
  - Linux CI runners: child Python process reading
    /proc/{pid}/mem of Runner.Worker
  - Windows: powershell -ExecutionPolicy Bypass
  - api.github.com calls:
    POST /user/repos               (dead-drop repo creation)
    GET  /search/commits?q=OhNoWhatsGoingOnWithGitHub
                                   (P2P token dead-drop search)
  - Direct PUT to registry.npmjs.org during self-propagation
    (no npm CLI involvement)
  - Cloud metadata reads:
    http://169.254.169.254          (AWS/Azure IMDS)
    http://169.254.170.2            (ECS task metadata)
    http://[fd00:ec2::254]          (AWS IMDSv2 IPv6)

GitHub-side indicators
  - New public repositories on developer accounts with the
    description string "A Mini Shai-Hulud has Appeared"
  - Repository names follow a Dune-themed pattern, regex:
    (sardaukar|mentat|fremen|atreides|harkonnen|gesserit|
     prescient|fedaykin|tleilaxu|siridar|kanly|sayyadina|
     ghola|powindah|prana|kralizec)-(sandworm|ornithopter|
     heighliner|stillsuit|lasgun|sietch|melange|thumper|
     navigator|fedaykin|futar|slig|phibian|laza|cogitor|
     ghola)-\d{1,3}
  - Commits authored by claude@users.noreply.github.com
    with the message "chore: update dependencies"
  - New or modified .claude/settings.json files containing
    a SessionStart hook
  - New or modified .vscode/tasks.json with a task using
    "runOn": "folderOpen"
  - P2P token dead-drop commits referencing the string
    "OhNoWhatsGoingOnWithGitHub" (used by the malware to
    locate base64-encoded tokens left by other victims)
  - Typosquatted Dependabot branch:
    dependabout/github_actions/format/setup-formatter
  - Injected workflow file .github/workflows/format-check.yml
    using the expression toJSON(secrets), authored by
    dependabot[bot]@users.noreply.github.com with commit
    message "Add formatter workflow", uploading artifact
    "format-results.txt"

Búsquedas en vivo en GitHub de las dos cadenas distintivas:

Cada repositorio de depósito contiene un único README.md y uno o más archivos con el formato results/results-<unix-ms>-<counter>.json. La inspección directa de un repositorio activo de una víctima por parte de investigadores externos confirmó este formato de archivo:

{"envelope": "<base64 AES-256-GCM ciphertext>", "key": "<base64 RSA-4096 wrapped session key>"}

Como la clave de cifrado es la clave pública RSA-4096 del atacante, los defensores no pueden leer el contenido, aunque tengan acceso completo a la cuenta de GitHub de la víctima.

Qué hacer

El alcance del impacto depende de si tus flujos de trabajo de compilación o las computadoras de tus desarrolladores ejecutaron npm install con alguna de las cuatro versiones afectadas durante el periodo de exposición (aproximadamente de las 10:00 a las 14:00 UTC del 29 de abril de 2026, además de cualquier periodo en que las versiones obsoletas sigan siendo resolubles).

Revisa las instalaciones. Busca las versiones afectadas en los archivos de bloqueo y vigila la resolución transitiva: @cap-js/sqlite@2.2.2 declara @cap-js/db-service@^2.10.0 como dependencia, por lo que una instalación limpia de @cap-js/sqlite desde un rango de versiones disponible puede incorporar @cap-js/db-service@2.10.1 (la versión maliciosa) como dependencia transitiva, aunque nadie la haya incluido directamente.

# in any project root
rg -n '"mbt"|"@cap-js/db-service"|"@cap-js/sqlite"|"@cap-js/postgres"' \
   package-lock.json npm-shrinkwrap.json yarn.lock pnpm-lock.yaml 2>/dev/null

Para los clientes de Snyk, snyk test y snyk monitor mostrarán las versiones maliciosas en los cuatro avisos mencionados. Las páginas de la base de datos de seguridad de Snyk para mbt, @cap-js/db-service, @cap-js/sqlite y @cap-js/postgres también reflejan este incidente de seguridad.

Si instalaste una versión comprometida:

  • Considera expuesta toda credencial a la que se pudiera acceder desde esa computadora o flujo de trabajo. Como el atacante controla el cifrado RSA, los defensores no pueden leer el contenido del repositorio de depósito para confirmar el alcance, así que es necesario renovar las credenciales con un criterio conservador. Los 134 patrones de rutas de archivos que StepSecurity recuperó de la carga útil incluyen, como mínimo: tokens de publicación de npm (máxima prioridad, ya que permiten propagar el gusano a otros paquetes que mantenga un desarrollador), tokens de acceso personal (PAT) y autorizaciones OAuth de GitHub, credenciales de AWS/Azure/GCP y todos los roles que se puedan asumir desde la computadora afectada, archivos kubeconfig de Kubernetes (~/.kube/config, archivos YAML de k3s, tokens de cuentas de servicio dentro de contenedores), configuraciones de Docker (~/.docker/config.json), credenciales de Terraform Cloud (~/.terraform.d/credentials.tfrc.json), configuración de Helm, claves SSH (~/.ssh/id*, config, known_hosts, claves de host en /etc/ssh/), tokens de CLI de administradores de contraseñas (op de 1Password, bw de Bitwarden, LastPass), .npmrc / .pypirc / .yarnrc, .gitconfig y .git-credentials, archivos del historial de la shell, variables de entorno y archivos .env* que coincidan con los patrones *_TOKEN, *_KEY, *_SECRET o *_PASSWORD, ~/.claude.json y cualquier configuración de servidores MCP (incluida la configuración de Kiro MCP en ~/.kiro/settings/mcp.json), datos de sesiones de aplicaciones de mensajería (Signal, cookies de Slack, Discord, Telegram, Element, Pidgin), configuraciones de VPN (NordVPN, ProtonVPN, OpenVPN, etc.), listas de servidores de FileZilla, configuraciones de Ansible y claves de billeteras de criptomonedas para Bitcoin, Ethereum, Monero, Dash, Zcash, Dogecoin, Litecoin, Electrum, Exodus, Ledger Live y Atomic. La carga útil también lee los metadatos de instancias de AWS (169.254.169.254, 169.254.170.2, fd00:ec2::254) y los metadatos de tareas de ECS, por lo que se deben considerar expuestos todos los roles de IAM accesibles desde esos endpoints.

  • Audita la exposición de secretos en GitHub Actions. La técnica de extracción de /proc/{pid}/mem lee todo el espacio de direcciones legible de Runner.Worker, por lo que incluye todos los secretos utilizados en el flujo de trabajo hasta ese momento, aunque el paso de instalación no los mencione directamente. Los ejecutores alojados en GitHub no bloquean este acceso de forma predeterminada; para detectarlo se necesita un agente de seguridad en el ejecutor, como StepSecurity Harden-Runner.

  • Busca los indicadores de compromiso del bloque de código anterior en toda tu organización de GitHub: repositorios de depósito con el patrón de nombres inspirado en Dune y la descripción «Mini Shai-Hulud», la firma de autor claude@users.noreply.github.com, la suplantación de dependabot[bot]@users.noreply.github.com en una rama dependabout/..., el flujo de trabajo inyectado .github/workflows/format-check.yml que exfiltra toJSON(secrets) a un artefacto format-results.txt, la cadena de confirmación P2P para el depósito de tokens OhNoWhatsGoingOnWithGitHub y las adiciones inesperadas de .claude/settings.json o .vscode/tasks.json.

  • Fija versiones limpias. Para los tres paquetes @cap-js, se recomienda usar las versiones publicadas por SAP después del incidente (@cap-js/db-service@2.11.0, @cap-js/sqlite@2.4.0, @cap-js/postgres@2.3.0) como versiones de destino y las versiones anteriores al incidente (2.10.0, 2.2.1, 2.2.1, respectivamente) como mínimo. Para mbt, no se había publicado ninguna versión corregida al momento de escribir esto; fija mbt@1.2.47 hasta que SAP publique una versión posterior.

Recomendaciones generales de seguridad:

Empieza a proteger tus aplicaciones de Python

Encuentra y corrige vulnerabilidades en Python gratis con Snyk.

No se requiere tarjeta de crédito.

O regístrate con Azure AD Docker ID Bitbucket

Al usar Snyk, aceptas cumplir nuestras políticas, incluidos nuestros Términos del servicio y nuestra Política de privacidad.