123% más CVE notificadas al día en 2026 que el año pasado.

Por qué CI

Por qué la seguridad de la cadena de suministro debe estar en su CI

El software que distribuye es lo que produjo su build de CI, a partir de lo que descargó en ese momento. Ese build es el único lugar donde puede ver qué entró, decidir qué puede entrar y registrar qué entró en la versión.

Actualizado el

What software supply chain security means

La definición de trabajo de la charla: su software es su propio código más todo aquello de lo que depende, y la cadena de suministro es cada paso que lleva esas piezas a una versión.

Petteri Pulkkinen y Erika Marttinen en Kubernetes Community Days Helsinki 2026, 2:35 a 4:28 de SBOMbastic: Getting Ready for Upcoming EU Cybersecurity Regulation in Software Supply Chains.

Su build de producción no es el build de su portátil

La mayoría de los equipos dan por hecho que el código que probaron en local es el código que se distribuye. El código fuente es el mismo, pero el software a menudo no lo es. Un build es código fuente más todo lo que descarga y todo lo que lo rodea en el momento de ejecutarse, y muy poco de eso es fijo.

Las dependencias sin fijar se resuelven de otra forma

Los rangos de dependencias son la norma. En npm, ^1.0.4 acepta cualquier versión 1.x posterior, de modo que el mismo package.json instala versiones distintas en días distintos. Un lockfile las fija, pero solo si está en el repositorio y el build lo respeta: npm ci falla cuando el lockfile y package.json no coinciden, mientras que npm install puede actualizar el lockfile sin avisar. Muchos proyectos ni siquiera incluyen uno. Express 5.2.1, un framework web muy utilizado, no lo hace.

Incluso una versión fijada es un nombre, no un archivo. La documentación de pip explica que fijar la versión no impide por sí solo que un índice de paquetes sirva archivos distintos para la misma versión, y por eso ofrece un modo de comprobación de hashes.

El tiempo cambia las entradas

Los registros cambian entre builds. Se publican versiones nuevas, se retiran las antiguas, y un rango que el lunes se resolvió de forma segura puede incorporar el martes una versión comprometida. Las etiquetas de contenedor también se mueven: la propia documentación de Docker advierte de que las etiquetas de imagen son mutables, es decir, de que un editor puede actualizar una etiqueta para que apunte a una imagen nueva, así que FROM node:20 no es la misma imagen base de un mes a otro, salvo que la fije por digest.

El tiempo también acaba dentro de la salida. El proyecto Reproducible Builds considera las marcas de tiempo la mayor fuente de problemas de reproducibilidad, porque muchísimas herramientas registran la fecha y la hora actuales en lo que compilan.

El entorno es distinto

  • Sistema operativo y arquitectura. Un portátil con macOS y ARM y un runner de CI con Linux y x86-64 instalan binarios precompilados distintos para el mismo paquete. Muchas herramientas de npm se distribuyen ahora como paquetes específicos de cada plataforma que envuelven un binario compilado.
  • Cadenas de herramientas. Las versiones del compilador, del entorno de ejecución y del gestor de paquetes divergen entre máquinas, salvo que se fijen todas.
  • Cachés. Su máquina y su CI restauran cachés distintas, creadas en momentos distintos a partir de resoluciones distintas.
  • Scripts de instalación y pasos de build. Los hooks de postinstalación, las acciones de configuración y los scripts de build descargan herramientas y datos durante el build. Nada de eso aparece en un manifiesto.
  • Configuración. Las variables de entorno, los flags de build y los secretos existen en CI y en ningún otro sitio.

El proyecto Reproducible Builds define un build reproducible como aquel en el que, con el mismo código fuente, el mismo entorno de build y las mismas instrucciones de build, cualquier parte puede recrear copias idénticas bit a bit de todos los artefactos especificados. Esa definición muestra cuánto hay que mantener constante. Los builds de la mayoría de los equipos no llegan a ese punto, y los que llegan han trabajado duro para conseguirlo. Hasta entonces, el único relato fiable de lo que se distribuyó es el registrado mientras se ejecutaba el build que se distribuyó.

A software supply chain, walked end to end

Petteri Pulkkinen y Erika Marttinen en Kubernetes Community Days Helsinki 2026, 15:20 a 16:38 de SBOMbastic: Getting Ready for Upcoming EU Cybersecurity Regulation in Software Supply Chains.

Dónde puede comprobarlo y qué ve cada lugar

Las comprobaciones de seguridad pueden ejecutarse en cuatro lugares. Cada uno tiene su función, pero solo uno ve el build que realmente produjo su versión.

Función En el build de CI Máquina del desarrollador Escaneo del repositorio Escaneo del artefacto
Ve las versiones que realmente llegaron a producción Registradas a medida que se descargan Una instalación distinta Solo si un lockfile las fija Lo que puede reconocer
Ve los paquetes transitivos y restaurados desde caché Su propia caché, no la de CI Solo el lockfile
Ve lo que descargan los scripts de instalación
Puede detener una llamada saliente maliciosa Política de salida en el runner
Detecta problemas antes de enviar el código En las pull requests
  • Incluido
  • En parte
  • No incluido

Un escaneo del repositorio indica lo que declara el proyecto. Un escaneo del artefacto terminado indica lo que puede reconocer en su interior. Ninguno vio cómo se hacía el build. Express 5.2.1 no incluye ningún lockfile en el repositorio, de modo que un escáner apuntado a un checkout limpio no tiene ninguna de las dependencias npm del proyecto que resolver e indica todo lo demás que reconozca. Apunte la misma herramienta a una copia instalada del mismo repositorio y un flag de catalogador vuelve a cambiar la respuesta. Lo que devuelve depende de lo que se hubiera instalado antes del escaneo, que es precisamente lo que un escaneo no controla. La página de SBOM durante el build explica por qué discrepan los escaneos y qué cambia al registrar el build.

El pipeline es un objetivo por sí mismo

CI es donde se encuentran el código fuente, las dependencias y los secretos, y por eso merece la pena atacarlo.

  • tj-actions/changed-files (2025). Una GitHub Action muy utilizada se vio comprometida e imprimió secretos de CI en los registros de build.
  • Codecov Bash Uploader (2021). Un script modificado, ejecutado en el CI de los clientes, envió variables de entorno al servidor de un atacante.
  • El gusano de npm Shai-Hulud (2025). Unos paquetes comprometidos robaron credenciales durante la instalación y las usaron para publicar más paquetes comprometidos.
  • xz utils (2024). Se ocultó una puerta trasera en los tarballs de la versión y en el propio proceso de build, no en el código fuente visible.

Todos ellos ejecutaron código durante un build o una instalación. Un escaneo del repositorio ejecutado antes, o un escaneo del artefacto ejecutado después, no habría visto lo que hizo el proceso de build. Los controles que vigilan y limitan a qué puede acceder un job tienen que estar donde se ejecuta el job. Eso también vale para las aplicaciones internas y de bajo perfil: estos ataques van a por el pipeline y los paquetes que comparten todas las aplicaciones, no a por lo que hace una aplicación. Consulte la seguridad de la cadena de suministro para software interno y de bajo riesgo.

Más código, más dependencias, menos personas que las lean

Los agentes de programación con IA escriben y cambian código más rápido de lo que los equipos pueden revisar cada línea, y añaden dependencias por el camino. También nombran paquetes que no existen: un estudio de USENIX Security 2025 sobre 576.000 muestras de código generado encontró tasas de paquetes alucinados de al menos el 5,2 % en los modelos comerciales y el 21,7 % en los modelos de código abierto. Si un atacante registra uno de esos nombres, el siguiente build que confíe en él instalará su paquete.

Todo cambio, lo haya escrito quien lo haya escrito, pasa por el build en su camino a producción. Eso convierte el build en el único punto de control que no depende de que alguien haya mirado.

Las evidencias tienen que describir lo distribuido

Las normativas y los clientes piden pruebas, no intenciones. El Cyber Resilience Act de la UE pide a los fabricantes identificar y documentar los componentes de sus productos y gestionar sus vulnerabilidades durante el periodo de soporte del producto. Una SBOM generada a partir de un manifiesto describe lo que pidió el proyecto. Una SBOM registrada a partir del build describe lo que entró en la versión de la que usted es responsable. Cuando se publica una nueva vulnerabilidad, la segunda le indica qué versiones están afectadas. Lea qué exige el CRA.

Qué debería significar «en CI»

Ejecutar un escáner como paso de CI es un comienzo, pero sigue mirando archivos después de que hayan llegado. Hacerlo bien en CI significa:

  1. Registrar, no deducir. Capturar cada paquete y descarga que el job obtiene realmente, incluidas las dependencias transitivas y todo lo restaurado desde una caché.
  2. Indicar lo completo que es el registro. Una SBOM debe indicar si cubre todo lo que descargó el job, no limitarse a enumerar lo que encontró.
  3. Controlar el tráfico de salida. Decidir a qué hosts puede acceder un job y detener el resto antes de que una dependencia comprometida pueda comunicarse con el exterior.
  4. Seguir vigilando después del lanzamiento. Volver a comprobar lo distribuido a medida que aparecen nuevas vulnerabilidades y convertir los hallazgos en correcciones.

Esto es lo que hace CRACI. Es un runner para sus jobs de GitHub Actions, de modo que registra lo que incorpora cada build, aplica la política de salida y monitoriza lo que usted ha distribuido. Migrar un workflow es cuestión de una sola línea: runs-on: craci. Consulte cómo funciona CRACI.

Lo que CI no sustituye

Llevar la seguridad de la cadena de suministro al build no hace opcionales las demás capas.

  • Las máquinas de los desarrolladores siguen guardando credenciales y ejecutando scripts de instalación. Protéjalas también; un portátil comprometido puede enviar código antes de que se ejecute ningún build.
  • La revisión de código y el análisis estático encuentran fallos en su propio código, algo que un registro de dependencias no hace.
  • La fijación de versiones, los lockfiles y los digests siguen siendo buenas prácticas. Reducen la diferencia entre builds; registrar el build le dice lo que ocurrió de todos modos.

El build no es el único lugar donde comprobar. Es el único lugar que ve el software que usted distribuye realmente.

Vea CRACI en su propio pipeline

Reserve una demo y repasaremos juntos sus builds, sus SBOM y sus evidencias de cumplimiento.

Reservar una demo