CommunityProgramación y desarrollogithub.com

hadifarnoud/supply-chain-security

Estándares de seguridad para la cadena de suministro y CI/CD: higiene de npm/pnpm, taxonomía de ataques de 14 elementos (typosquatting, robo de cuentas, envenenamiento de caché, reetiquetado, manipulación de lockfiles, malware replicante), endurecimiento de GitHub Actions, pinning de Docker, comandos de escaneo rápido de IOC y hallazgos de auditoría por proyecto. Útil para cualquier trabajo con npm/pnpm/lockfiles, cambios en .github/workflows, Dockerfile o pinning de imágenes, revisión de configuraciones de MCP/herramientas de desarrollo o una auditoría de cadena de suministro.

¿Qué es supply-chain-security?

Este skill define estándares de seguridad para la cadena de suministro de software, aplicables a todos los proyectos. Proporciona una taxonomía detallada de 14 vectores de ataque, incluyendo typosquatting, robo de cuentas de mantenedores, envenenamiento de imágenes Docker y ataques a herramientas de seguridad, con comandos de detección específicos. También cubre la higiene de npm/pnpm (como el pinning de versiones y el uso de lockfiles), el endurecimiento de flujos de trabajo de GitHub Actions (pinning con SHA, evitación de pull_request_target riesgoso) y el pinning de imágenes Docker. El skill se enfoca en plataformas npm, pnpm, GitHub Actions y Docker, ofreciendo reglas claras y comprobables para prevenir vulnerabilidades en la cadena de suministro.

Compatible con✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/hadifarnoud/supply-chain-security/tree/HEAD

Installed? Explore more Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Estándares de Seguridad en la Cadena de Suministro

Aplica a todos los proyectos. Reglas revisadas el 2026-11-11 (post gusano Shai-Hulud / Mini Shai-Hulud).


Valores predeterminados a nivel de máquina (~/.npmrc)

minimum-release-age=1440        # solo pnpm — MINUTOS (1440 = 24h)
min-release-age=1               # solo npm 12+ — DÍAS (1 = 24h)

Los dos gestores de paquetes usan nombres de clave diferentes Y unidades diferentes. Verificado el 2026-08-21 leyendo el código fuente de cada herramienta: pnpm computa Date.now() - minimumReleaseAge * 60 * 1e3 (minutos); la definición de configuración de npm para min-release-age lleva hint: '<days>'. Ambas líneas son necesarias — una no cubre a la otra, y copiar 1440 en la clave de npm significaría 1440 días y bloquearía esencialmente cada instalación.

npm imprime Unknown user config "minimum-release-age" al instalar y advierte que dejará de funcionar en una versión futura importante. Eso es inevitable mientras la clave esté en ~/.npmrc: pnpm 11 eliminó la escritura de configuración global (pnpm config set --global ahora redirige a un pnpm-workspace.yaml por proyecto), por lo que ~/.npmrc es el único lugar donde puede vivir una puerta global de pnpm. Acepte la advertencia; no elimine la clave.

No confíe en estas — verificadas como inertes

  • block-exotic-subdependencies — no aparece en el código fuente de npm ni de pnpm. Nunca ha hecho nada. Las dependencias exóticas deben detectarse mediante revisión, no mediante esta clave.

  • ignore-scripts=true — este skill afirmaba anteriormente que estaba configurado globalmente. No está configurado, y npm config get ignore-scripts devuelve false, por lo que los scripts de ciclo de vida sí se ejecutan al instalar.

    Decidido el 2026-08-21: déjelo apagado. No lo habilite. Postinstall es el vector de compromiso principal de npm, por lo que esta es una brecha conocida y aceptada — no un descuido que corregir. Activarlo globalmente rompe las compilaciones nativas (esbuild, swc, sharp, node-gyp) en todos los proyectos y la rotura se manifiesta lejos de la causa. La puerta de antigüedad de lanzamiento de 24 horas anterior asume este riesgo en su lugar. Si un proyecto específico alguna vez necesita aislamiento de scripts, limítelo allí — nunca globalmente.

Verifique afirmaciones como estas contra la herramienta en lugar de contra este archivo — las tres entradas aquí eran incorrectas cuando se auditaron.


Taxonomía de ataques a la cadena de suministro (referencia antes de auditar)

1. Typosquatting / Confusión de dependencias

Paquete con nombre casi idéntico a uno popular, o un paquete público que coincide con un nombre con ámbito interno. 454,648 paquetes npm maliciosos publicados solo en 2025. Detectar: npm info <pkg> | grep -E 'created|repository' en paquetes desconocidos. Cotejar contra nombres de registro internos.

2. Robo de cuenta de mantenedor

El atacante suplanta a un mantenedor, publica una nueva versión con una carga útil posterior a la instalación. Shai-Hulud septiembre 2025 afectó a chalk, debug, ansi-styles (2.6 mil millones de descargas semanales). Axios (100M+/semana) afectado en marzo de 2026 mediante ingeniería social de RPDC. Detectar: npm diff <pkg>@<ultimo-conocido-bueno> <pkg>@latest -- package.json scripts — buscar nuevos scripts de ciclo de vida agregados en versiones de parche.

3. Secuestro de repositorio / Ocupación de espacio de nombres

El atacante registra un nombre de usuario de GitHub abandonado o un espacio de nombres de npm, recrea el repositorio y sirve código malicioso. Detectar: Verifique el campo repository en package.json; marque cuentas de GitHub creadas después de la fecha de la primera publicación npm del paquete.

4. Inyección en tubería CI/CD (pull_request_target / envenenamiento de caché)

El atacante abre un PR contra un repositorio con pull_request_target que comparte una caché con un trabajo de publicación privilegiado. Envenena el almacén de pnpm; el siguiente flujo de trabajo de lanzamiento filtra el token OIDC de npm. Vector TanStack (noviembre de 2025, Mini Shai-Hulud mayo de 2026, 300+ paquetes, 16M descargas semanales). Detectar:

grep -r "pull_request_target" .github/workflows/
grep -r "cache" .github/workflows/ | grep -i "pnpm\|npm\|store"

Regla estricta: Nunca use pull_request_target si el flujo de trabajo descarga el código del PR o comparte una caché con un trabajo privilegiado.

5. Envenenamiento de imagen Docker

El atacante compromete las credenciales de Docker Hub y sobrescribe las etiquetas de imagen existentes (incluyendo latest) con binarios maliciosos. Las etiquetas 0.69.4–0.69.6 y latest de Trivy aquasec/trivy envenenadas en marzo de 2026. KICS abril de 2026 — cinco etiquetas sobrescritas; escanea configuraciones de Terraform/K8s que contienen secretos. Detectar: docker inspect <image> --format '{{.Id}}' vs. un digest anclado en la configuración. Regla estricta: Ancle todas las imágenes a @sha256: digest. Nunca use latest para imágenes de herramientas de seguridad.

6. Reetiquetado de acciones de GitHub

El atacante compromete el token de un mantenedor de acción, mueve una etiqueta de versión existente para que apunte a código malicioso. tj-actions/changed-files CVE-2025-30066 (marzo de 2025, 23,000+ repositorios) volcó todos los secretos de CI a los registros. Mayo de 2026: etiquetas de acciones populares redirigidas a commits impostores. Detectar:

grep -r "uses:.*@v[0-9]" .github/workflows/   # marca anclado por etiqueta (malo)
grep -r "uses:.*@[a-f0-9]\{40\}" .github/workflows/  # anclado por SHA (correcto)

Regla estricta: Ancle cada acción de terceros a un SHA de commit completo de 40 caracteres, no a una etiqueta de versión. actions/* (primeros) pueden usar etiquetas de versión mayor.

7. Manipulación de lockfile / Omisión de integridad (clase PackageGate)

El atacante modifica el lockfile para sustituir una versión de paquete maliciosa o elimina hashes de integridad para que la siguiente instalación obtenga silenciosamente un tarball diferente. Se documentaron seis vulnerabilidades de día cero en lockfiles en enero de 2026 (Koi Security). Detectar:

grep -E '"resolved".*git\+|tarball' package-lock.json pnpm-lock.yaml
grep -v "integrity" pnpm-lock.yaml | grep "resolved"

Regla estricta: CI debe usar pnpm install --frozen-lockfile o npm ci — nunca npm install solo.

8. Sombreado de subdependencias

El atacante apunta a una dependencia transitiva de 3+ niveles de profundidad. @ctrl/tinycolor fue un nodo de propagación de Shai-Hulud. Detectar: npm ls --all 2>/dev/null | grep -E "postinstall|preinstall". Use socket scan en PRs.

9. Transferencia de mantenedor por ingeniería social

El atacante se hace pasar por reclutador o socio comercial para obtener derechos de publicación npm. UNC1069 (RPDC) atacó al mantenedor de Axios en marzo de 2026, también intentó contra el CEO de Socket, el creador de Lodash, el líder de Fastify. Detectar: npm owner ls <pkg> para dependencias críticas; monitoree nuevos colaboradores antes de un lanzamiento sospechoso.

10. Protestware (Sabotaje intencional del mantenedor)

El mantenedor inyecta intencionalmente código destructivo. colors.js v1.4.44–1.4.2 (enero de 2022, bucle infinito), node-ipc v10.1.1–10.1.3 (marzo de 2022, archivos eliminados en IPs rusas). Tres nuevas versiones maliciosas de node-ipc en mayo de 2026. Detectar:

npm diff <pkg>@<prev> <pkg>@<new> -- lib/
grep -r "networkInterfaces\|geoip\|fs.rmdir\|fs.unlink" node_modules/<pkg>/

Ancle node-ipc, colors, faker a versiones exactas conocidas como buenas.

11. Malware autorreplicante similar a gusano

La carga útil roba tokens/PATs de npm y publica autónomamente versiones maliciosas de otros paquetes que la víctima mantiene. Observado por primera vez en Shai-Hulud septiembre de 2025; Mini Shai-Hulud mayo de 2026 (300+ paquetes, 16M descargas semanales, npm + PyPI simultáneamente). Detectar IOCs:

find .github/workflows -name "*.js"            # bundle.js en flujos de trabajo
grep -ri "shai-hulud" .                        # cadena del gusano
find node_modules -name "data.json" -newer package.json  # preparación de exfiltración
find node_modules -name "cloud.json"

12. Cargas útiles latentes / condicionadas por entorno

La carga útil solo se activa cuando AWS_SECRET_ACCESS_KEY, GITHUB_TOKEN o CI=true están presentes — evade los escáneres de sandbox. Detectar:

grep -r "process.env.AWS_SECRET\|process.env.GITHUB_TOKEN\|process.env.NPM_TOKEN" node_modules/

Marque cualquier paquete que lea estas variables sin una razón legítima para hacerlo.

13. Herramienta de seguridad como vector de ataque

Los atacantes apuntan específicamente a herramientas de escaneo de seguridad (Trivy, KICS, Semgrep) porque se ejecutan con acceso elevado a secretos y configuraciones de infraestructura en CI. Trivy y KICS fueron afectadas en marzo-abril de 2026. Regla estricta: Ancle todas las imágenes Docker de herramientas de seguridad a digest, no a etiqueta. Verifique los digests fuera de banda contra las notas de lanzamiento del proveedor.

14. Dependencias fuera de registro / CDN

Los paquetes resueltos desde URLs de git, tarballs de GitHub o CDNs personalizadas (ej. cdn.sheetjs.com) eluden las puertas de seguridad y procedencia del registro, y tampoco están cubiertos por la puerta de antigüedad de lanzamiento — solo se aplica a versiones de registro. Algunos carecen completamente de hashes de integridad. Nada bloquea estos automáticamente; deben detectarse en la revisión. Detectar:

grep -E '"resolved".*github\.com|cdn\.' package-lock.json pnpm-lock.yaml
grep -E '"version":\s*"(git\+|https?:)' package.json

Higiene de npm/pnpm por proyecto

  • Confirme lockfiles. CI debe usar pnpm install --frozen-lockfile (o npm ci). Nunca npm install solo en CI.
  • Ancle packageManager en package.json para fijar la versión de pnpm/npm.
  • Ancle paquetes en espacios de nombres comprometidos a versiones exactas: @tanstack/*, posthog-node, @mistralai/*, @langchain/mistralai, @ctrl/*, ngx-*, rxnt-*, @zapier/*, @postman/*, @uipath/*, agent-mcp, @semgrep/*, node-ipc, colors, faker.
  • Sin versiones de comodín "*" en package.json.
  • Sin URLs de pkg.pr.new — estas son compilaciones de vista previa de PR efímeras, no artefactos inmutables.
  • Para proyectos npm/yarn, refleje las mismas puertas de npmrc en su .npmrc local.
  • Prefiera pnpm para proyectos nuevos. No migre proyectos funcionales solo por seguridad.

Endurecimiento de GitHub Actions

Reglas estrictas

  • Nunca use pull_request_target si el flujo de trabajo descarga el código del PR, ejecuta install/build/test del código del PR o comparte una caché con un flujo de trabajo privilegiado.
  • pull_request_target solo es aceptable para leer metadatos del PR (etiquetas, comentarios, título) sin descarga.
  • No comparta cachés entre trabajos desencadenados por PR y trabajos de publicación/lanzamiento.
  • Nunca use curl | bash o wget | sh contra una rama mutable (@main, @master) en CI. Siempre ancle los scripts del instalador a un lanzamiento específico y verifique una suma de verificación.

Guardas de workflow_run

Al usar workflow_run para encadenar un trabajo privilegiado después de un flujo de trabajo padre, el if: DEBE afirmar todo lo siguiente:

if: >
  github.event_name == 'workflow_dispatch' ||
  (github.event.workflow_run.conclusion == 'success' &&
   github.event.workflow_run.head_branch == 'main' &&
   github.event.workflow_run.head_repository.full_name == github.repository &&
   github.event.workflow_run.event == 'push')

Anclaje de acciones

  • Ancle cada acción de terceros a un SHA de commit completo de 40 caracteres, no @v1/@v6.
  • Agregue un comentario con la etiqueta legible para humanos para auditoría: docker/login-action@65d0a9e # v3
  • Las acciones de actions/* (primeros) pueden usar etiquetas de versión mayor.
  • Obtenga SHAs actuales: gh api repos/<owner>/<action>/git/ref/tags/<tag>
  • Automaticélo con: npx pin-github-action .github/workflows/*.yml
  • Minimice permissions: por trabajo. Por defecto, contents: read. Agregue id-token: write solo en el paso de publicación.

Flujos de trabajo de publicación npm

  • Requiera 2FA en la cuenta npm: npm profile enable-2fa auth-and-writes.
  • Use publicación confiable (OIDC) en lugar de secretos NPM_TOKEN de larga duración.
  • Agregue --provenance (o provenance: true) para que los consumidores puedan verificar el origen.
  • Publique solo desde un release.yml desencadenado por push de etiqueta en main. Nunca desde flujos de trabajo desencadenados por PR.

Higiene de Docker / contenedores

  • Ancle cada FROM a un digest: FROM node:22-slim@sha256:<hash>
  • Nunca use latest o imágenes sin etiqueta en Dockerfiles de producción o CI.
  • Las imágenes de herramientas de seguridad (Trivy, KICS, Semgrep, Snyk, Grype, Hadolint) son las de mayor riesgo — ancle estas primero.
  • Obtenga digests actuales: docker buildx imagetools inspect node:22-slim --format '{{json .Manifest.Digest}}'
  • Para imágenes de registro privado: publique con etiquetas inmutables + digests.

Herramientas de desarrollo y archivos de configuración

  • Nunca almacene tokens API o secretos en texto plano en ~/.cursor/mcp.json, ~/.claude/settings.json o archivos de configuración similares. Use variables de entorno o un llavero.
  • Ancle paquetes del servidor MCP a versiones exactas ([email protected], no mcp-remote@latest).
  • Verifique ~/.vscode/tasks.json y ~/.cursor/ en busca de hooks de ejecución automática inesperados después de cualquier incidente en la cadena de suministro.

Detección / monitoreo

  • Instale zizmor o snyk-labs/github-actions-scanner en CI para cualquier repositorio con flujos de trabajo.
  • Agregue la aplicación de GitHub socket.dev en cualquier repositorio que publique paquetes (cualquier biblioteca publicable).
  • Suscríbase a las fuentes RSS de avisos de seguridad npm y a las fuentes de malware PyPI.

Lista de verificación de escaneo rápido de IOC

# IOCs de Shai-Hulud / gusano
grep -ri "shai-hulud" .
find .github/workflows -name "*.js"
find node_modules -name "cloud.json"
# Patrones de flujo de trabajo comprometidos
grep -r "pull_request_target" .github/workflows/
grep -r "curl.*|.*sh\|wget.*|.*sh\|base64.*eval" .github/workflows/
# Acciones sin anclar
grep -r "uses:.*@v[0-9]" .github/workflows/
# Dependencias exóticas en lockfile
grep -E '"resolved".*git\+|cdn\.' package-lock.json pnpm-lock.yaml
grep -v integrity pnpm-lock.yaml | grep resolved
# Docker
grep -r "FROM.*:latest\|FROM.*[^@]$" Dockerfile* docker-compose*.yml

Skills relacionados