Un puente se mantiene en servicio durante cincuenta años siguiendo un programa de inspección fijo, sometido a pruebas de carga y mantenido durante todo ese tiempo. El motor de un jet vuela con el mismo diseño durante décadas bajo una supervisión normativa continua. En la mayoría de las disciplinas de ingeniería, el objetivo es un diseño estable y probado combinado con un mantenimiento activo. Los diseños más nuevos se tratan con mucha más escrutinio porque nunca se han probado realmente.
Pero, por alguna razón, en la ingeniería de software ocurre lo contrario. La versión más nueva se considera la más segura. Y ese instinto ha tenido consecuencias muy negativas en el pasado. Una puerta trasera se introdujo sigilosamente en dos versiones específicas de xz-utils, concretamente la 5.6.0 y la 5.6.1, plantada por un infiltrado que había pasado de dos a tres años tramando cómo obtener autoridad sobre las publicaciones. Cualquiera que siguiera ejecutando la línea anterior 5.4 nunca estuvo expuesto, pero todo aquel que descargó la versión más reciente, lo que normalmente se le dice a los equipos de seguridad que hagan, estaba ejecutando una ruta SSH con puerta trasera. La recomendación posterior de la CISA fue degradar la versión en lugar de actualizarla.
Ya hemos argumentado antes, en lo que llamamos “la trampa de la actualización”, que aplicar parches en cuanto aparece una CVE es una falsa economía; estás eligiendo entre congelar el sistema o aceptar cualquier cambio que venga con la corrección. xz-utils nos muestra la otra cara de la misma moneda. Mantenerse sin cambios fue la decisión segura, y la versión más nueva resultó ser la trampa.
Una forma de comprobar esto es preguntar a un equipo de seguridad cuántas CVE abiertas tiene; sabrán responder rápidamente. Pero si preguntas por qué un paquete o una imagen de contenedor específica ejecuta la versión que ejecuta, lo más probable es que obtengas un “no lo sé”. Simplemente es así, ¿verdad? Por lo general, se basa en lo que estaba disponible cuando comenzó el proyecto, y actualizar parecía implicar más trabajo del que valía la pena. Yendo un paso más allá, si pides un registro por escrito de esa decisión, es probable que recibas una respuesta más tajante del tipo ¿por qué íbamos a hacer eso?

¿Dónde está el fallo?
A menudo se hace creer a los ingenieros que una imagen de contenedor o un paquete se vuelve más arriesgado a medida que el número de versión envejece. Pero el ejemplo de xz-utils demuestra que esto no es cierto; la versión anterior era segura porque nada malicioso había llegado a ella todavía, y los equipos que la ejecutaban no se habían apresurado a adoptar la última versión en cuanto salió. Por supuesto, cabe la posibilidad de que muchos equipos simplemente no hayan tenido tiempo de actualizarla, pero quisieran hacerlo. Eso sigue siendo mejor que no saber qué versión estás ejecutando ni por qué, que es el verdadero fallo aquí.
En su lugar, los equipos deben tener en cuenta que si disponen de una versión de una biblioteca que ha sido probada, comprendida y en la que se confía, mantener esa estabilidad aporta un valor genuino. El monitoreo comienza en el momento en que un desarrollador, agente o canal de compilación solicita una imagen base de contenedor o un paquete de código abierto, evaluándolo antes de que entre en el entorno. Es la primera decisión en una cadena de decisiones que se toman.
Una actualización también es una decisión
En algún momento saldrá una nueva versión, pero aplicar un parche a una CVE significa aceptar todo lo demás que se haya incluido en esa versión. Eso incluye elementos como dependencias transitivas, valores predeterminados modificados y rutas de código que nadie del equipo ha leído. La mayor parte del tiempo ese riesgo es invisible y no pasa nada. Pero, y es un gran pero, puede salir mal. lodash pasó un tiempo de 2026 con una vulnerabilidad divulgada de inyección de código arbitrario que afectaba a todas las versiones publicadas. Cuando la solución finalmente se lanzó como la versión 4.18.0, falló de inmediato porque el parche intercambió una función interna diferente que nunca se había importado, provocando que proyectos reales fallaran en cuestión de un día.
La versión se retiró de inmediato, con una nota que remitía a los usuarios a lodash 4.17.21 En cambio, el cambio que provocó incompatibilidades no tenía nada que ver con la propia vulnerabilidad, sino que se trataba de un error de empaquetado que se incluyó junto con la corrección de seguridad. La corrección real se incorporó en la versión 4.18.1.
Ninguna de las opciones sobre la mesa era realmente segura. Actualizar a 4.18.0 rompía las compilaciones de inmediato. Mantenerse en 4.17.21 dejaba la vulnerabilidad abierta, mientras que todas las versiones anteriores a 4.18.0 seguían siendo vulnerables. Algunos equipos volvieron a la versión 4.17.x específicamente para **Escape**r de la compilación rota, cambiando una compilación funcional por una ruta de inyección de código activo sin necesariamente darse cuenta de que ese era el trato que habían hecho.
En este caso, los equipos mejor posicionados fueron aquellos que sabían si su propia aplicación llegaba a invocar el _.template ruta afectada con entradas no confiables, y podían sopesar esa exposición real frente a la alternativa rota, en lugar de decantarse por cualquiera de las opciones sin saber lo que realmente les costaba.
Solucionar la vulnerabilidad sin reemplazar todo lo que la rodea
Aplicar un backport cambia la ecuación. Toma el parche específico para la vulnerabilidad concreta y lo aplica a la versión que ya está en ejecución, en lugar de arrastrar todo lo demás que se lanzó junto con ella en el código fuente original (upstream). Al aplicarlo a una imagen de contenedor, el CVE se soluciona sin obligar a usar una nueva imagen base. Al aplicarlo a un paquete, se implementa el mismo arreglo sin necesidad de saltar forzosamente a la última versión, justo el salto que rompió proyectos reales que ejecutaban lodash 4.18.0. Puedes solucionar el problema de seguridad sin cambiar todo lo que lo rodea.
Un SBOM debe ganarse su lugar, no limitarse a existir
Un SBOM, como tantos documentos relacionados con el cumplimiento normativo, a menudo se genera una vez y se archiva. Eso te dice lo que había en el sistema el día que alguien ejecutó el informe. Pero el SBOM puede hacer mucho más por tu postura de seguridad que eso. Puede servir como una línea base de software confiable y ayudarte a gestionarla de forma continua. Para lograrlo, debes asegurarte de mantenerlo actualizado y contrastarlo con las nuevas vulnerabilidades a medida que se descubren. Para mí, esa es la señal más clara de que una organización sigue haciendo un seguimiento del software que ejecuta en lugar de conformarse con lo que ya hay.
Queremos que el SBOM no sea solo un inventario o un artefacto de cumplimiento. Debe ser una superficie gobernada y mantenida activamente.
¿Qué es lo que tiene que cambiar entonces?
Todas estas son decisiones que es necesario tomar. Algunas se refieren a un componente de software específico en un momento dado, como evaluar una solicitud, fijar tu versión y aplicar un backport en lugar de forzar una actualización. Otras, como mantener un SBOM actualizado, tienen que ver con los procesos establecidos. Cada una de ellas es, en realidad, una decisión sobre en qué confiar.
Lo más fácil es dejar las cosas como están porque «funciona». Pero eso de que «funciona» no es del todo cierto, ¿verdad? Que algo funcione ahora no significa que vaya a funcionar siempre, ni que sea la forma más segura de hacer las cosas, ni que sea el mejor modo de operar.
Desde nuestra perspectiva, el enfoque más proactivo y consciente de la seguridad consistiría en controlar el cambio en el punto de entrada: evaluar los paquetes antes de que un desarrollador, agente o sistema de compilación los consuma. A partir de ahí, deberías tener la potestad de decidir de forma proactiva qué entra, fijar lo que consideras de confianza, mantenerlo y cambiarlo únicamente cuando exista una razón de peso.
Mantenerse en una versión no debería significar seguir expuesto. Aikido Libraries aplica retrocompatibilidad de parches a la versión que ya estás ejecutando, sin actualizaciones ni migraciones forzosas. Empieza a parchear aquí.