Devsecops

Por qué es importante fijar la versión de las librerías en el desarrollo de software

Publicado: 22 de mayo de 2024 | Actualizado: 29 de junio de 2026

Recientemente se ha reportado un bug en el SDK de Docker para Python que ha generado problemas en las aplicaciones que usaban la librería para ejecutar contenedores y afectado gravemente a la disponibilidad de las mismas.

Definir una versión fija de las librerías que usamos en un proyecto puede parecer un detalle técnico menor. Sin embargo, es una práctica fundamental para mantener la seguridad, la estabilidad y la disponibilidad de una aplicación.

Cuando una dependencia se actualiza automáticamente sin haber sido probada, puede introducir errores, incompatibilidades o incluso riesgos de seguridad. Por eso, en proyectos profesionales, no basta con usar “la última versión disponible”. Es necesario controlar qué versión se instala, cuándo se actualiza y cómo se valida antes de llegar a producción.

Esta práctica es especialmente importante dentro de un enfoque DevSecOps, donde la seguridad se integra en todo el ciclo de vida del software: desde el desarrollo hasta el despliegue y la operación.

Qué significa fijar una versión de una librería

Fijar una versión, también conocido como pinned version, significa indicar de forma exacta qué versión de una dependencia debe usar una aplicación.

Por ejemplo, en Python no es lo mismo escribir:

requests

que escribir:

requests==2.31.0

En el primer caso, el gestor de paquetes puede instalar la última versión disponible. En el segundo, se instala una versión concreta.

Esta diferencia es importante porque una actualización automática puede cambiar el comportamiento de la aplicación sin que el equipo lo haya previsto.

Qué ocurrió con Docker SDK for Python y Requests

En mayo de 2024 se reportó un problema relacionado con Docker SDK for Python y la librería Requests.

Al publicarse la versión 2.32.0 de Requests, algunas aplicaciones que usaban Docker SDK for Python empezaron a fallar con errores relacionados con el esquema http+docker.

El problema no estaba necesariamente en la aplicación final, sino en una incompatibilidad entre dependencias. Es decir, una librería se actualizó y eso provocó fallos en otra que dependía de ella.

En algunos casos, la solución temporal fue fijar Requests en una versión anterior, como 2.31.0, hasta que el ecosistema de dependencias se actualizara correctamente.

Este caso demuestra algo muy importante: una dependencia sin versión fija puede romper una aplicación aunque el equipo no haya cambiado su propio código.

Por qué usar siempre la última versión no siempre es buena idea

Actualizar librerías es necesario. De hecho, muchas actualizaciones corrigen vulnerabilidades, mejoran el rendimiento o solucionan errores.

El problema aparece cuando las actualizaciones se aplican de forma automática y sin validación previa.

Usar siempre la última versión disponible puede provocar:

  • Incompatibilidades entre librerías.
  • Fallos inesperados en producción.
  • Cambios de comportamiento no documentados.
  • Problemas de disponibilidad.
  • Nuevas vulnerabilidades.
  • Errores difíciles de reproducir.
  • Roturas en pipelines de despliegue.

Por eso, lo recomendable no es dejar de actualizar, sino actualizar de forma controlada.

El paralelismo con el uso de latest en Docker

Este problema es muy parecido al uso del tag latest en imágenes Docker.

Cuando una imagen usa latest, no se está indicando una versión concreta. Esto puede provocar que una aplicación despliegue una imagen diferente a la probada inicialmente.

Por ejemplo:

FROM python:latest

Esta configuración puede parecer cómoda, pero no es recomendable en producción.

Una opción más segura sería:

FROM python:3.12.4-slim

De esta forma, el equipo sabe exactamente qué versión está usando y puede probar cualquier actualización antes de aplicarla.

Lo mismo ocurre con las librerías. Usar versiones concretas ayuda a construir aplicaciones más predecibles, seguras y fáciles de mantener.

Cómo afecta esto a la seguridad del software

No fijar versiones no solo puede afectar a la disponibilidad de una aplicación. También puede afectar a su seguridad e integridad.

Una dependencia mal gestionada puede abrir la puerta a problemas como:

  • Instalación de versiones vulnerables.
  • Introducción de cambios no revisados.
  • Dependencias manipuladas.
  • Ataques a la cadena de suministro.
  • Fallos en entornos productivos.
  • Dificultad para saber qué versión está realmente desplegada.

Por eso, la gestión de dependencias es una parte clave del desarrollo de software seguro.

Dentro de un modelo SSDLC, las dependencias deben revisarse desde las primeras fases del desarrollo, no solo cuando la aplicación ya está en producción.

Qué es un ataque de Dependency Confusion

Uno de los riesgos relacionados con una mala gestión de dependencias es el ataque conocido como Dependency Confusion.

Este ataque se hizo especialmente conocido en 2021 y consiste, de forma simplificada, en aprovechar cómo un gestor de paquetes resuelve las dependencias.

El atacante publica en un repositorio público una librería con el mismo nombre que una dependencia interna de una empresa. Si la configuración no está bien protegida, el gestor de paquetes puede descargar la versión pública maliciosa en lugar de la privada legítima.

El resultado puede ser muy grave: el atacante consigue introducir código malicioso dentro del entorno de desarrollo, integración o producción.

Este tipo de ataque demuestra que la seguridad no depende solo del código propio, sino también de cómo se gestionan las librerías, los repositorios y los procesos de construcción.

Buenas prácticas para gestionar dependencias de forma segura

Para reducir riesgos, es recomendable aplicar una serie de buenas prácticas en todos los proyectos de software.

Buena prácticaPor qué es importante
Fijar versiones de libreríasEvita actualizaciones inesperadas
Usar archivos lockGarantiza instalaciones reproducibles
Revisar dependencias periódicamenteDetecta versiones vulnerables o desactualizadas
Automatizar análisis de seguridadPermite identificar riesgos antes
Separar dependencias públicas y privadasReduce el riesgo de Dependency Confusion
Validar actualizaciones antes de producciónEvita errores por incompatibilidad
Mantener inventario de componentesFacilita la respuesta ante vulnerabilidades
Evitar latest en producciónMejora la trazabilidad y estabilidad

Usar archivos lock para asegurar instalaciones reproducibles

Los archivos lock ayudan a garantizar que una aplicación se instala siempre con las mismas versiones de dependencias.

Algunos ejemplos son:

  • package-lock.json en npm.
  • yarn.lock en Yarn.
  • poetry.lock en Poetry.
  • Pipfile.lock en Pipenv.
  • composer.lock en Composer.
  • Gemfile.lock en Ruby.
  • go.sum en Go.

Estos archivos permiten que el entorno de desarrollo, integración continua y producción usen las mismas versiones.

Esto reduce el riesgo de que una aplicación funcione en el equipo de un desarrollador, pero falle en producción por haber instalado una dependencia distinta.

Automatización DevSecOps para controlar dependencias

La revisión manual de dependencias no es suficiente en proyectos modernos. Las aplicaciones pueden tener decenas o cientos de librerías directas e indirectas.

Por eso, la automatización DevSecOps es clave.

Integrar controles de seguridad en procesos de integración continua permite detectar problemas antes de que lleguen a producción.

Algunos controles recomendados son:

  • Análisis de dependencias vulnerables.
  • Revisión de versiones obsoletas.
  • Detección de paquetes maliciosos.
  • Análisis de licencias.
  • Generación de SBOM.
  • Bloqueo de builds con vulnerabilidades críticas.
  • Validación de dependencias privadas.
  • Revisión de imágenes Docker.
  • Alertas ante nuevas vulnerabilidades.

El objetivo no es frenar el desarrollo, sino evitar que una dependencia insegura llegue a producción sin control.

La importancia de un servicio de gestión de vulnerabilidades

Cuando se publica una vulnerabilidad en una librería, las empresas necesitan responder rápido.

Para hacerlo bien, deben saber:

  • Qué aplicaciones usan esa librería.
  • Qué versión está instalada.
  • Si la vulnerabilidad afecta realmente a su entorno.
  • Qué sistemas están en producción.
  • Qué prioridad tiene la corrección.
  • Qué equipos deben actuar.

Un servicio de gestión de vulnerabilidades ayuda a identificar, priorizar y corregir estos riesgos de forma ordenada.

Esto es especialmente importante cuando una vulnerabilidad afecta a componentes muy extendidos o a dependencias usadas por muchas aplicaciones.

Sin esta visibilidad, la respuesta suele ser lenta, manual y poco eficiente.

El papel de los equipos en la seguridad de dependencias

La seguridad de las dependencias no depende solo de herramientas. También depende de que los equipos conozcan las buenas prácticas y las apliquen de forma consistente.

Un programa de Security Champions puede ayudar a crear referentes de seguridad dentro de los equipos de desarrollo.

Estos perfiles pueden apoyar en tareas como:

  • Revisar dependencias críticas.
  • Promover el uso de versiones fijas.
  • Ayudar a interpretar alertas de seguridad.
  • Coordinar correcciones con el equipo de ciberseguridad.
  • Impulsar buenas prácticas en los pipelines.
  • Reducir errores recurrentes en el desarrollo.

De esta forma, la seguridad se integra mejor en el trabajo diario de los equipos.

Cómo actualizar librerías de forma segura

Fijar versiones no significa no actualizar nunca.

Significa actualizar con control.

Un proceso seguro de actualización debería incluir:

  1. Revisar qué dependencias tienen nuevas versiones.
  2. Consultar si corrigen vulnerabilidades.
  3. Probar la actualización en un entorno controlado.
  4. Ejecutar pruebas automáticas.
  5. Revisar posibles cambios incompatibles.
  6. Validar el impacto en seguridad y estabilidad.
  7. Aprobar el cambio.
  8. Desplegar de forma progresiva.
  9. Monitorizar el comportamiento tras el despliegue.

Este proceso permite mantener las aplicaciones actualizadas sin asumir riesgos innecesarios.

Recomendaciones finales

Para evitar problemas como el ocurrido con Docker SDK for Python y Requests, conviene aplicar estas recomendaciones:

  • No dejar dependencias sin versión definida.
  • Evitar rangos demasiado amplios en producción.
  • Usar archivos lock.
  • Revisar actualizaciones antes de aplicarlas.
  • Automatizar el análisis de dependencias.
  • Separar repositorios públicos y privados.
  • Controlar las imágenes Docker usadas en producción.
  • Evitar tags latest.
  • Mantener un inventario de componentes.
  • Integrar controles de seguridad en CI/CD.
  • Formar a los equipos de desarrollo.

Estas medidas ayudan a mejorar la estabilidad, la seguridad y la trazabilidad de las aplicaciones.

Conclusión

Definir versiones fijas de las librerías no es solo una buena práctica técnica. Es una medida esencial para proteger la seguridad y disponibilidad de las aplicaciones.

El caso de Docker SDK for Python y Requests demuestra que una actualización automática puede provocar fallos importantes aunque el código de la aplicación no haya cambiado.

Además, una mala gestión de dependencias puede facilitar ataques como Dependency Confusion o introducir componentes vulnerables en producción.

En Ciberso ayudamos a las organizaciones a mejorar la seguridad de sus desarrollos mediante un enfoque DevSecOps, integrando controles de seguridad, gestión de dependencias, análisis de vulnerabilidades y automatización en todo el ciclo de vida del software.

Solicita más información

Si necesitas contactar con nosotros puedes rellenar formulario a continuación. Nos pondremos en contacto contigo lo antes posible.