Actualiza dependencias transitivas con PNPM: Soluciona las vulnerabilidades de seguridad sin romper nada
Solucionar vulnerabilidades de seguridad puede ser una tarea frustrante, especialmente cuando involucra dependencias transitivas. Aprende cómo actualizarlas sin afectar tus dependencias directas.
Hoy en día, las vulnerabilidades de seguridad son un problema común en el desarrollo de software. Afortunadamente, tenemos herramientas como GitHub Dependabot que nos ayudan a mantener nuestras dependencias actualizadas con detección automática y solicitudes de extracción.
Sin embargo, no siempre funciona como se espera. Dado que algunas dependencias son transitivas, actualizarlas puede ser una tarea difícil para estas herramientas, ya que no conocen el impacto de los cambios y qué decisión tomar cuando hay conflictos. Necesitamos manejar estos casos manualmente.
Métodos que no funcionan
- Comandos oficiales como
pnpm up
desordenarán tu archivopnpm-lock.yaml
. Hay un problema sobre esto que sigue abierto al momento de escribir. - Instalar la última versión de la dependencia directa que tiene la dependencia transitiva objetivo puede no funcionar. Si la dependencia directa no actualizó las definiciones de la versión, la dependencia transitiva no se actualizará, ya que ha sido resuelta y bloqueada en el archivo
pnpm-lock.yaml
.
La solución
El campo overrides
es una característica poderosa en PNPM que te permite sobrescribir algunas resoluciones de versión. Usaremos esta función para actualizar dependencias transitivas y hacer el cambio lo más mínimo posible.
Usemos la alerta anterior de Dependabot como ejemplo. Nos dice que el paquete follow-redirects
tiene una vulnerabilidad de seguridad, y la versión corregida es 1.15.6
. Sin embargo, la dependencia directa gatsby
usa axios
, que depende de [email protected]
.
Paso 1: Encuentra la dependencia transitiva
Hay muchas maneras de localizar la dependencia transitiva, pero te recomendaría la forma más sencilla: buscar en el archivo pnpm-lock.yaml
.
¿Qué tal "pnpm why"?
El comando pnpm why <package>
es útil, de hecho. Sin embargo, puede confundirte en este caso. Por ejemplo, cuando ejecuto pnpm why follow-redirects
, aquí hay una parte de la salida:
En realidad, solo existe una resolución para follow-redirects
en el archivo pnpm-lock.yaml
. El comando pnpm why
puede mostrarte múltiples rutas que dependen de la misma versión del paquete.
Paso 2: Añadir los overrides
El caso más fácil es cuando solo existe una resolución en el archivo pnpm-lock.yaml
. Puedes añadir el override directamente en el archivo package.json
:
Si estás en un workspace, deberías añadir el override al archivo package.json
en la raíz del workspace.
Paso 3: Aplica los cambios
Ejecuta pnpm install
para aplicar los cambios. Podemos ver que el paquete follow-redirects
se actualiza a 1.15.6
en el archivo pnpm-lock.yaml
con cambios mínimos.
Ahora puedes eliminar el campo overrides
del archivo package.json
para mantenerlo limpio. Luego ejecuta pnpm install
nuevamente para validar que los cambios se pueden aplicar sin el campo overrides
.
Solución de problemas
Los pasos anteriores son el caso ideal. Las cosas pueden no salir siempre como se espera. Aquí hay algunos consejos para solucionar problemas:
La versión es revertida después de eliminar el campo "overrides"
Esto puede suceder cuando el paquete dependiente tiene una versión fija o un rango que no incluye la versión objetivo. Revisa el archivo package.json
del paquete dependiente, en este caso, axios
, para ver si esto aplica.
Si es así, necesitas mantener el campo overrides
en el archivo package.json
hasta que el paquete dependiente actualice las definiciones de la versión.
Hay múltiples resoluciones para la dependencia transitiva
A medida que el proyecto crece, el archivo pnpm-lock.yaml
puede inflarse con múltiples resoluciones para el mismo paquete. Por ejemplo, puede haber dos versiones principales del mismo paquete foo
:
El informe de vulnerabilidad muestra que [email protected]
tiene un problema de seguridad que se soluciona en 1.0.1
, y [email protected]
no se ve afectado. No podríamos simplemente añadir un override a foo
:
- Si añadimos un override
"foo": "^1.0.1"
, el[email protected]
se degradará a1.0.1
. Esto puede romper el proyecto, ya que[email protected]
puede tener algunas características nuevas que son utilizadas en los paquetes dependientes. - Si añadimos un override
"foo": "^2.0.0"
, el[email protected]
se actualizará a2.0.0
. Esto puede romper el proyecto, ya que[email protected]
puede tener algunos cambios que no son compatibles.
Suponiendo que foo
sigue Semantic Versioning, podemos añadir un override como este:
Esto solo actualizará [email protected]
a 1.0.1
y mantendrá [email protected]
sin cambios.
Conclusión
Antes de que PNPM soporte la actualización directa de dependencias transitivas, el campo overrides
es una buena solución para arreglar vulnerabilidades de seguridad sin romper nada. Espero que este artículo te ayude a manejar estos casos más eficientemente. En Logto, usamos este método para mantener nuestras dependencias actualizadas y seguras.