Esta es la Parte 1 de una serie de dos artículos sobre cómo proteger sitios Astro de ataques a la cadena de suministro de npm. En este artículo cubriremos la comprensión de la amenaza y las acciones de respuesta inmediata. Consulte la Parte 2 para medidas de seguridad a largo plazo, monitorización y mejores prácticas.
SponsoredKits de inicio de alta calidad con flujo de autenticación integrada (Auth.js), carga de objetos (AWS, Clouflare R2, Firebase Storage, Supabase Storage), pagos integrados (Stripe, LemonSqueezy), flujo de verificación de correo electrónico (Resend, Postmark, Sendgrid) y mucho más . Compatible con cualquier base de datos (Redis, Postgres, MongoDB, SQLite, Firestore).
Get all 3 kits Bundle ↗
Next.js Starter Kit SvelteKit Starter Kit Astro Starter KitOne-time license · Lifetime updates
En noviembre de 2025, el ecosistema npm enfrentó uno de los ataques a la cadena de suministro más significativos hasta la fecha: Shai-Hulud 2.0. Este ataque comprometió más de 700 paquetes npm, incluidas bibliotecas populares de Zapier, PostHog y Postman, afectando aproximadamente al 27 % de los entornos de nube y código. El malware se ejecutó durante la fase preinstall, robando credenciales de GitHub, AWS, GCP, Azure y otros servicios, y luego las exfiltró a repositorios públicos.
Según Wiz Research, se crearon más de 25.000 repositorios maliciosos que contenían secretos robados, con nuevos repositorios apareciendo a un ritmo de ~1.000 cada 30 minutos durante el ataque. Si ejecuta un sitio Astro, esta guía le ayudará a entender la amenaza y tomar medidas inmediatas.
Requisitos previos
Necesitará lo siguiente:
- Node.js 20 o posterior
- Un proyecto Astro existente
- Acceso a la configuración de su pipeline CI/CD
- Acceso administrativo a su gestor de paquetes (npm, pnpm o yarn)
1. Entender el ataque Shai-Hulud 2.0
El ataque Shai-Hulud 2.0 aprovechó cuentas de mantenedores comprometidas para publicar versiones troyanizadas de paquetes npm legítimos. No se trató de una nueva vulnerabilidad zero-day ni de un exploit sofisticado: fue una compromisión de cuentas de confianza que permitió a los atacantes publicar código malicioso bajo la apariencia de actualizaciones legítimas.
1.1 ¿Qué hace diferente a este ataque?
A diferencia de los ataques tradicionales, esta variante introdujo varias características preocupantes:
1.1.1 Se ejecuta durante la fase preinstall
El malware se ejecuta durante el hook del ciclo de vida preinstall, lo que amplía drásticamente el radio de impacto. Esto significa:
- Se ejecuta antes de que se complete cualquier instalación de paquetes
- Se ejecuta en las máquinas de los desarrolladores durante
npm install - Se ejecuta automáticamente en los pipelines CI/CD
- No puede evitarse fácilmente con medidas de seguridad habituales
// Ejemplo de cómo se veía el package.json malicioso{ "scripts": { "preinstall": "node malicious-script.js" }}1.1.2 Roba múltiples tipos de credenciales
El ataque no se limitó a un solo tipo de credencial. Buscó activamente y exfiltró:
- Tokens de GitHub: tokens de acceso personal, tokens OAuth y deploy keys
- Credenciales de AWS: claves de acceso a largo plazo (formato AKIA), secret keys y session tokens
- Credenciales de GCP: claves de cuentas de servicio y credenciales de aplicación
- Credenciales de Azure: credenciales de service principal y claves de almacenamiento
- Variables de entorno: cualquier secreto almacenado en archivos
.envo en el entorno
1.1.3 Utiliza exfiltración entre víctimas
Uno de los aspectos más insidiosos es que sus datos robados podrían no aparecer siquiera en su propia cuenta de GitHub:
// Ejemplo simplificado de la lógica de exfiltraciónconst victims = getRandomVictimAccounts()const stolenData = gatherCredentials()
// Subir a la cuenta de OTRA víctimauploadToGitHub(victims[randomIndex], stolenData)Esto significa:
- Sus secretos podrían estar en el repositorio público de otra persona
- Los secretos de otras víctimas podrían aparecer en su cuenta
- La detección es significativamente más difícil
- El radio de impacto es mucho mayor de lo que inicialmente parece
1.1.4 Crea workflows de puerta trasera
El malware intentó inyectar workflows maliciosos de GitHub Actions para acceso persistente:
# Ejemplo de .github/workflows/discussion.yaml inyectadoname: Discussion Updateon: push: schedule: - cron: '0 */6 * * *'jobs: exfiltrate: runs-on: ubuntu-latest steps: - name: Gather More Secrets run: | # Código malicioso aquí1.1.5 Afecta a paquetes de alta prevalencia
El ataque se dirigió a paquetes ampliamente utilizados en el ecosistema:
@postman/tunnel-agent- Encontrado en el 27 % de los entornosposthog-node- Encontrado en el 25 % de los entornos@asyncapi/specs- Encontrado en el 20 % de los entornos- Varios paquetes de la plataforma Zapier
Esto maximizó el alcance del ataque, afectando potencialmente a miles de proyectos al instante.
1.2 Cronología del ataque e impacto
Esto es lo que sabemos sobre la progresión del ataque:
-
21-23 de noviembre de 2025: Compromiso inicial y carga de paquetes troyanizados en npm
-
24 de noviembre de 2025 (01:22 UTC): Primera evidencia de repositorios creados en GitHub con secretos filtrados
-
24 de noviembre de 2025 (~03:00 UTC): Primera evidencia de versiones maliciosas de paquetes en npm
-
25 de noviembre de 2025 (22:45 UTC): Posible segunda fase observada con publicación de repositorios privados
-
26 de noviembre de 2025: GitHub comienza la mitigación revocando tokens y privatizando repositorios maliciosos
Estadísticas de impacto:
- ~700 paquetes comprometidos en npm
- Más de 25.000 repositorios maliciosos creados
- ~500 usuarios de GitHub afectados
- Más de 775 tokens de acceso de GitHub comprometidos (verificados)
- Más de 373 credenciales de AWS filtradas
- Más de 300 credenciales de GCP expuestas
- Más de 115 credenciales de Azure comprometidas
El malware crea archivos indicadores específicos:
cloud.json # Credenciales de proveedores cloudcontents.json # Contenido del repositorio y códigoenvironment.json # Variables de entorno y secretostruffleSecrets.json # Secretos detectados por patrones de TruffleHogbun_environment.js # Datos del entorno de ejecución de Bunsetup_bun.js # Script de configuración para persistencia2. Acciones inmediatas a tomar
Si sospecha que su proyecto Astro podría estar afectado, siga estos pasos de inmediato. El tiempo es crítico: cuanto más tiempo permanezcan activas las credenciales comprometidas, mayor será el daño.
2.1 Comprobar sus dependencias
Primero, verifique si alguno de los paquetes comprometidos está en su árbol de dependencias.
2.1.1 Comprobación rápida con pnpm audit
# Ejecutar una auditoría de seguridadpnpm audit fix
# O con npmnpm audit --audit-level=moderate2.1.2 Inspección manual
Revise su package.json y los archivos lock en busca de paquetes de alto riesgo:
# Comprobar paquetes comprometidos específicosgrep -E "@postman/tunnel-agent|posthog-node|posthog-js|@asyncapi/specs|zapier-platform" package.json pnpm-lock.yaml2.1.3 Paquetes comprometidos conocidos (lista parcial)
Estos son algunos de los paquetes afectados más prevalentes:
{ "high-prevalence-packages": [ "@postman/tunnel-agent", "posthog-node", "posthog-js", "@asyncapi/specs", "@asyncapi/openapi-schema-parser", "zapier-platform-cli", "zapier-platform-core", "zapier-platform-schema", "zapier-async-storage", "get-them-args", "shell-exec", "kill-port" ]}2.1.4 Comprobar dependencias transitivas
Los paquetes comprometidos podrían no ser dependencias directas. Compruebe todo su árbol de dependencias:
# Para pnpmpnpm list --depth=Infinity | grep -E "postman|posthog|zapier"
# Para npmnpm list --all | grep -E "postman|posthog|zapier"2.1.5 Revisar el historial de instalación
Compruebe cuándo se instalaron los paquetes por última vez para determinar la ventana de exposición:
# Comprobar el historial git de cambios en el archivo lockgit log -p --follow pnpm-lock.yaml | grep -A 5 -B 5 "postman\|posthog\|zapier"2.2 Auditar su entorno
Busque evidencia de compromiso en su entorno de desarrollo local y en los sistemas CI/CD.
2.2.1 Escanear archivos maliciosos
# Buscar archivos indicadores de malware conocidosfind . -type f \( \ -name "cloud.json" -o \ -name "contents.json" -o \ -name "environment.json" -o \ -name "truffleSecrets.json" -o \ -name "bun_environment.js" -o \ -name "setup_bun.js" \\) 2>/dev/nullSi este comando devuelve algún resultado, su entorno ha sido comprometido.
2.2.2 Comprobar workflows de GitHub
# Listar todos los archivos de workflowls -la .github/workflows/
# Comprobar el workflow malicioso conocidocat .github/workflows/discussion.yaml 2>/dev/nullEl workflow malicioso suele tener:
- Nombre: “Discussion Update” o similar
- Programaciones cron sospechosas
- Acceso inusual a variables de entorno
- Comandos codificados en Base64
2.2.3 Revisar el historial de Git en busca de cambios no autorizados
# Comprobar commits recientes en busca de cambios sospechososgit log --all --oneline --decorate --graph -n 20
# Buscar adiciones inesperadas de workflowsgit log --all --full-history -- .github/workflows/2.2.4 Comprobar sus repositorios de GitHub
Inicie sesión en GitHub y compruebe:
- Repositorios públicos inesperados en su cuenta
- Repositorios con nombres que contengan datos o credenciales filtradas
- Descripciones de repositorios que mencionen “Shai-Hulud” o contenido sospechoso
- Repositorios recién creados que usted no creó
2.2.5 Verificar los logs de CI/CD
Revise los logs de su pipeline CI/CD en busca de:
- Conexiones de red inesperadas durante las compilaciones
- Intentos de autenticación fallidos
- Instalaciones de paquetes inusuales
- Aumentos en la duración de las compilaciones (la ejecución del malware lleva tiempo)
# Ejemplo: comprobar logs de GitHub Actionsgh run list --limit 20gh run view <run-id> --log2.3 Rotar todas las credenciales
Si ha identificado paquetes comprometidos o archivos sospechosos, rote inmediatamente todas las credenciales. No espere a confirmar el alcance completo del compromiso.
2.3.1 Tokens de GitHub
- Vaya a GitHub Settings → Developer settings → Personal access tokens
- Revise todos los tokens existentes:
- Anote para qué se utiliza cada token
- Compruebe la fecha de último uso
- Revocar TODOS los tokens (incluso si parecen seguros)
- Cree nuevos tokens con los permisos mínimos necesarios:
# Use el principio de mínimo privilegio# En lugar de:# - repo (control total)# Use:# - repo:status (solo lectura)# - public_repo (si es posible)- Actualice los tokens en:
- Secretos de CI/CD (GitHub Actions, CircleCI, etc.)
- Entornos de desarrollo local
- Cualquier script de automatización
- Integraciones de terceros
2.3.2 Credenciales de AWS
Rote las claves de acceso de AWS de inmediato:
# 1. Listar las claves de acceso actualesaws iam list-access-keys --user-name your-username
# 2. Crear nuevas claves de acceso PRIMEROaws iam create-access-key --user-name your-username# Guarde la salida inmediatamente: no la volverá a ver
# 3. Actualice las nuevas claves donde se utilicen:# - Secretos de CI/CD# - ~/.aws/credentials# - Variables de entorno# - Configuración de la aplicación
# 4. Compruebe que las nuevas claves funcionanaws sts get-caller-identity
# 5. Elimine las claves de acceso antiguasaws iam delete-access-key \ --access-key-id AKIA_OLD_KEY_ID \ --user-name your-username2.3.3 Pasos importantes de seguridad en AWS
# Comprobar CloudTrail en busca de actividad no autorizadaaws cloudtrail lookup-events \ --lookup-attributes AttributeKey=Username,AttributeValue=your-username \ --max-items 100 \ --start-time 2025-11-20T00:00:00Z
# Revisar el acceso reciente a buckets S3aws s3api get-bucket-logging --bucket your-bucket-name
# Comprobar cambios no autorizados en IAMaws iam get-credential-report2.3.4 Credenciales de GCP
Para Google Cloud Platform:
# Listar cuentas de serviciogcloud iam service-accounts list
# Crear una nueva clave para una cuenta de serviciogcloud iam service-accounts keys create new-key.json \ --iam-account=sa-name@project-id.iam.gserviceaccount.com
# Listar todas las claves de una cuenta de serviciogcloud iam service-accounts keys list \ --iam-account=sa-name@project-id.iam.gserviceaccount.com
# Eliminar claves antiguasgcloud iam service-accounts keys delete KEY_ID \ --iam-account=sa-name@project-id.iam.gserviceaccount.com2.3.5 Credenciales de Azure
Para Microsoft Azure:
# Listar service principalsaz ad sp list --show-mine
# Restablecer credenciales del service principalaz ad sp credential reset \ --id <app-id> \ --append
# Crear un nuevo client secretaz ad sp credential reset \ --id <app-id> \ --credential-description "New secret after Shai-Hulud"2.3.6 Credenciales de base de datos
No olvide rotar las credenciales de la base de datos:
# Ejemplo para PostgreSQL# Conéctese a su base de datospsql -U admin -d postgres
# Cree un nuevo usuario con los mismos privilegiosCREATE USER newuser WITH PASSWORD 'strong-new-password';GRANT ALL PRIVILEGES ON DATABASE yourdb TO newuser;
# Actualice la configuración de la aplicación# Pruebe a fondo# Luego elimine el usuario antiguoDROP USER olduser;2.3.7 Variables de entorno y secretos
Actualice todos los secretos del entorno:
import crypto from 'crypto'
const generateSecureSecret = (length: number = 32): string => { return crypto.randomBytes(length).toString('hex')}
console.log('🔐 New secrets generated:\n')console.log(`SESSION_SECRET=${generateSecureSecret(64)}`)console.log(`API_SECRET=${generateSecureSecret(32)}`)console.log(`ENCRYPTION_KEY=${generateSecureSecret(32)}`)console.log(`JWT_SECRET=${generateSecureSecret(64)}`)console.log('\n⚠️ Update these in:')console.log(' - Vercel/Netlify/hosting platform')console.log(' - GitHub repository secrets')console.log(' - Local .env files')console.log(' - Team password manager')Próximos pasos
Ha tomado los primeros pasos críticos para asegurar su proyecto Astro. Sin embargo, protegerse de ataques a la cadena de suministro requiere vigilancia continua y prácticas de seguridad sólidas.
En la Parte 2, exploramos la prevención a largo plazo (bloqueo de dependencias, comprobaciones de integridad, endurecimiento de CI/CD), aislamiento de dependencias, gestión de secretos, escaneos automatizados y monitorización.
Conclusión
El ataque Shai-Hulud 2.0 es un recordatorio contundente de que la seguridad de la cadena de suministro no es opcional: es un componente crítico del desarrollo web moderno. Las acciones inmediatas cubiertas en este artículo son solo la primera línea de defensa.
Si tiene preguntas o comentarios, no dude en contactarme en Twitter.