GitHub ha anunciado un conjunto de cambios críticos en npm versión 12, cuyo principal punto es la desactivación por defecto de la ejecución de los install scripts de las dependencias. El cambio afecta a todos los desarrolladores que utilizan el ecosistema de Node.js: el comando npm install dejará de ejecutar automáticamente los scripts preinstall, install y postinstall de las dependencias sin una aprobación explícita. El lanzamiento de npm 12 está previsto para el próximo mes. Para prepararse, GitHub recomienda actualizar a npm 11.16.0 o posterior y usar el comando npm approve-scripts para aprobar explícitamente los paquetes de confianza.
Qué cambia exactamente
GitHub ha descrito los scripts del ciclo de vida que se ejecutan durante la instalación como «la mayor superficie de ejecución de código de todo el ecosistema npm». El problema es que npm install ejecuta scripts de cada dependencia transitiva; por tanto, basta con que un único paquete esté comprometido en cualquier punto del árbol de dependencias para que pueda ejecutar código arbitrario en la máquina del desarrollador o en el entorno de CI/CD.
npm 12 introduce tres limitaciones clave:
- Bloqueo de install scripts:
npm installno ejecutará los scriptspreinstall,installypostinstallde las dependencias si no están permitidos explícitamente en la configuración del proyecto. - Bloqueo de dependencias Git: las dependencias Git directas y transitivas no se resolverán sin especificar explícitamente la bandera
--allow-git. - Bloqueo de remotas
Las compilaciones nativas a través de node-gyp también quedarán bloqueadas: los paquetes con un archivo binding.gyp sin un install script explícito también se bloquearán, ya que npm ejecuta para ellos el comando implícito node-gyp rebuild. Los scripts prepare de dependencias Git, de archivos y simbólicas se bloquean de forma análoga.
Cierre de la evasión a través de .npmrc
Merece una atención especial el hecho de que el valor de --allow-git pase a ser none por defecto. Esto cierra un vector de ataque en el que un archivo .npmrc dentro de una dependencia Git podía redefinir el ejecutable de Git. Es llamativo que esta ruta de ejecución de código funcionara incluso al utilizar la bandera --ignore-scripts, que hasta ahora se consideraba la principal medida de protección frente a scripts maliciosos durante la instalación.
A quién afecta
Los cambios afectarán prácticamente a todo el ecosistema de Node.js. Se verán especialmente impactados:
- Proyectos con módulos nativos: cualquier dependencia que use node-gyp para compilar add-ons en C/C++ requerirá una aprobación explícita.
- Pipelines de CI/CD: las compilaciones automatizadas que dependen de scripts postinstall para configurar el entorno pueden fallar si no se actualiza la configuración.
- Proyectos con dependencias Git: los monorepositorios y los proyectos que hacen referencia directamente a repositorios privados requerirán un permiso explícito.
Si no se toma ninguna medida, la actualización a npm 12 provocará fallos en la instalación de dependencias: todos los scripts no aprobados simplemente dejarán de ejecutarse.
Cómo prepararse
GitHub recomienda el siguiente orden de acciones:
- Actualizar npm a la versión 11.16.0 o posterior.
- Realizar la instalación estándar de dependencias y revisar las advertencias que se muestren.
- Ejecutar
npm approve-scripts --allow-scripts-pendingpara ver la lista de paquetes que incluyen scripts. - Aprobar los paquetes de confianza y confirmar en el repositorio el
package.jsonactualizado.
Tras la actualización a npm 12 solo se ejecutarán los scripts aprobados explícitamente. Todo lo que quede sin aprobar será bloqueado.
Cabe señalar que anteriormente npm ya introdujo el ajuste min-release-age, que permite rechazar versiones de paquetes publicadas hace menos días de los especificados, como protección frente a publicaciones maliciosas recientes. La desactivación por defecto de los scripts en npm 12 es una continuación lógica de esta estrategia de refuerzo de la seguridad de la cadena de suministro.
El paso de npm a un modelo de aprobación explícita de scripts supone un cambio fundamental desde la «confianza por defecto» hacia el «zero trust» en la gestión de dependencias. Los equipos de desarrollo deberían comenzar ya la auditoría de los scripts de sus dependencias en npm 11.16.0 o superior, para que la actualización a npm 12 no provoque fallos inesperados en los procesos de build.