Lo que cambió el incidente AsyncAPI
Durante dos semanas de julio de 2026, cinco versiones de paquetes de AsyncAPI circularon con una procedencia OIDC firmada, un mecanismo introducido precisamente para garantizar el origen de un paquete. Los atacantes habían comprometido el pipeline de publicación, no la clave de firma. Resultado: npm audit signatures devolvía un resultado limpio y los gestores de dependencias no lanzaban ninguna alerta. Esto cambia la manera de pensar la seguridad de las dependencias: la firma prueba la integridad del paquete en el momento de su publicación, no la integridad del proceso que lo produjo.
Medidas concretas que hay que implantar
- Política --frozen-lockfile — prohibir cualquier modificación silenciosa del package-lock.json en CI (
npm cilo impone de forma nativa,--frozen-lockfilepara yarn/pnpm). - Verificación de los hashes en CI — añadir un job que compare los hashes SHA-512 del lockfile con los registros de npm y detecte cualquier divergencia.
- SCA automatizado — integrar un escáner de composición de software (OWASP Dependency-Check, Trivy, Snyk) como etapa bloqueante del pipeline.
- Procedencia SLSA de nivel 2 como mínimo — en sus publicaciones, generar y adjuntar las atestaciones SLSA; en sus consumos, comprobar que los paquetes críticos disponen de ellas.
- Vigilancia de los digests de imagen — anclar cada imagen Docker a su digest sha256 en lugar de a una etiqueta flotante.
- Alertas sobre las versiones nuevas no planificadas — configurar Dependabot o Renovate para que avisen de toda versión publicada fuera de su ventana habitual.
Lo que el lockfile garantiza — y lo que no garantiza
El package-lock.json registra la versión exacta y el hash de cada dependencia resuelta. Impide una subida de versión silenciosa en un npm install posterior. Lo que no hace: comprobar que el contenido del paquete correspondiente no ha cambiado en el registry después de su resolución inicial, ni que el pipeline que produjo el paquete estaba a su vez sano. El lockfile es una instantánea de lo que usted resolvió un día concreto, no una garantía sobre la cadena de fabricación aguas arriba.
Endurecer su pipeline CI paso a paso
Pasar a `npm ci` y desterrar `npm install` en CI
Sustituya todo
npm installde sus workflows pornpm ci. El comando se niega a ejecutarse si el package-lock.json falta o diverge del package.json. Añada--ignore-scriptssi su árbol contiene postinstall de terceros sin auditar.Activar `npm audit` en modo bloqueante
Añada
npm audit --audit-level=highdespués denpm ciy antes del build. En GitHub Actions, la etapa falla si se detecta un resultado de severidad alta. Diferencie las dependencias de desarrollo con--omit=dev.Verificar los hashes con `npm audit signatures`
Desde npm 8.8,
npm audit signaturescomprueba que cada paquete instalado tiene una firma válida registrada en el registry. Ejecute este comando después denpm ci. No detecta los casos como el de AsyncAPI (firma válida pero pipeline comprometido), pero constituye una primera red de seguridad.Integrar un escáner SCA (Trivy u OWASP Dependency-Check)
Añada un job SCA independiente en su workflow de CI. Trivy analiza el package-lock.json directamente (
trivy fs --scanners vuln .) sin necesidad de instalar las dependencias. Configúrelo para que falle ante las CVE con una puntuación CVSS superior a 7.Consumir y emitir atestaciones SLSA
Para sus propios paquetes publicados, active la procedencia SLSA en su workflow de publicación (GitHub Actions slsa-framework/slsa-github-generator). Para las dependencias de terceros, verifique las atestaciones de los paquetes críticos a través de la API de Sigstore.
Fijar las actions de CI y las imágenes a su digest sha256
En sus archivos .github/workflows/*.yml o .gitlab-ci.yml, sustituya las etiquetas flotantes por digests sha256. Una etiqueta flotante puede apuntar a una imagen distinta al día siguiente de un compromiso del registry.
No parchee nunca una dependencia directamente en producción modificando node_modules a mano: el lockfile divergiría y el siguiente despliegue desde la CI reintroduciría el paquete original. Toda corrección pasa por el lockfile versionado y se vuelve a aplicar desde la CI.
Integración en su workflow Git alojado
Estos controles son etapas del pipeline, no costumbres manuales: pertenecen a su ci.yml (GitHub Actions) o a su .gitlab-ci.yml, y se disparan en cada push y en cada pull request. En un repositorio autoalojado (Gitea, GitLab CE), se aplican las mismas recetas. Proteja su rama principal con una regla de merge condicionada a la CI en verde y bloquee los merges si alguno de esos jobs SCA falla.