10 mejores prácticas de seguridad para npm
Juan Picado
19 de febrero de 2019
0 minutos de lectura¿Te preocupan las vulnerabilidades de npm? Tanto los desarrolladores de frontend como los de backend deben tener en cuenta las mejores prácticas de seguridad para npm. Auditar la seguridad del código abierto es fundamental para integrar la seguridad desde las primeras etapas del desarrollo, y la seguridad de los paquetes de npm debe ser una prioridad, ya que incluso se ha descubierto que la herramienta oficial de línea de comandos de npm es vulnerable.
En esta edición de nuestra guía práctica, nos enfocaremos en diez mejores prácticas de seguridad para npm y consejos de productividad, tanto para quienes mantienen proyectos de código abierto como para los desarrolladores. Empecemos con nuestra lista de 10 mejores prácticas de seguridad para npm, comenzando con un error clásico: ¡publicar paquetes de npm que incluyen contraseñas!
1. Evita publicar secretos en el registro de npm
Ya sea que uses claves de API, contraseñas u otros secretos, pueden filtrarse con facilidad al control de código fuente o incluso a un paquete publicado en el registro público de npm. Es posible que tengas secretos en tu directorio de trabajo, en archivos específicos como .env, que deberían agregarse a .gitignore para evitar que se incluyan en el SCM. Pero ¿qué pasa cuando publicas un paquete de npm desde el directorio del proyecto?
La CLI de npm empaqueta el proyecto en un archivo tar (tarball) para enviarlo al registro. Los siguientes criterios determinan qué archivos y directorios se agregan al tarball:
Si existe un archivo
.gitignoreo.npmignore, su contenido se usa como patrón de exclusión al preparar el paquete para su publicación.Si existen ambos archivos de exclusión, se publica en el registro todo lo que no esté en
.npmignore. Esta condición suele causar confusión y puede provocar filtraciones de secretos. Los desarrolladores pueden actualizar el archivo.gitignore, pero olvidar actualizar también.npmignore. Así, un archivo potencialmente confidencial podría quedar fuera del control de código fuente, pero incluirse de todos modos en el paquete de npm.
Otra buena práctica es usar la propiedad files en package.json, que funciona como una lista de permitidos y especifica los archivos que se incluirán en el paquete que se va a crear e instalar (mientras que el archivo de exclusión funciona como una lista de bloqueados). Puedes usar la propiedad files junto con un archivo de exclusión para determinar qué archivos se deben incluir o excluir explícitamente del paquete. Si usas ambos, la propiedad files de package.json tiene prioridad sobre el archivo de exclusión.
Al publicar un paquete, la CLI de npm muestra detalladamente el archivo que se está creando. Para tener más cuidado, agrega el argumento --dry-run al comando de publicación. Así podrás revisar primero cómo se crea el tarball sin publicarlo en el registro.
En enero de 2019, npm publicó en su blog que había agregado un mecanismo que revoca automáticamente un token si detecta que se publicó junto con un paquete.
2. Asegúrate de usar el archivo de bloqueo
Recibimos con los brazos abiertos la llegada de los archivos de bloqueo de paquetes, que permiten instalaciones deterministas en distintos entornos y garantizan que se respeten las dependencias esperadas al colaborar en equipo. ¡Todo va bien! O eso creía… ¿Qué habría pasado si hubiera hecho un cambio en el archivo package.json del proyecto, pero hubiera olvidado confirmar también el archivo de bloqueo?
Yarn y npm se comportan igual al instalar dependencias. Cuando detectan una inconsistencia entre el archivo package.json del proyecto y el archivo de bloqueo, la resuelven basándose en el manifiesto package.json e instalan versiones distintas de las registradas en el archivo de bloqueo.
Esta situación puede ser peligrosa en los entornos de compilación y producción, ya que podrían incorporarse versiones no deseadas de paquetes y perderse todas las ventajas del archivo de bloqueo.
Por suerte, puedes indicarles a Yarn y npm que respeten un conjunto específico de dependencias y sus versiones, consultando el archivo de bloqueo. Cualquier inconsistencia hará que se cancele la instalación. Los comandos son los siguientes:
Si usas Yarn, ejecuta
yarn install --frozen-lockfile.Si usas npm, ejecuta
npm ci.
3. Reduce la superficie de ataque al ignorar los scripts de ejecución
La CLI de npm funciona con los scripts de ejecución de los paquetes. Si alguna vez ejecutaste npm start o npm test, también usaste estos scripts. La CLI de npm se basa en scripts que los paquetes pueden declarar y permite definir scripts que se ejecutan en puntos específicos durante la instalación de un paquete en un proyecto. Por ejemplo, algunas de estas entradas de enganche de scripts pueden ser scripts postinstall que ejecuta un paquete durante su instalación para realizar tareas de mantenimiento.
Con esta capacidad, los actores maliciosos pueden crear o modificar paquetes para llevar a cabo acciones maliciosas ejecutando cualquier comando cuando se instala el paquete. Algunos casos que ya hemos visto son el incidente de eslint-scope, que recopiló tokens de npm, y el incidente de crossenv, junto con otros 36 paquetes que aprovecharon un ataque de typosquatting en el registro de npm.
Aplica estas mejores prácticas de seguridad para npm y reduce la superficie de ataque de los módulos maliciosos:
Investiga siempre los módulos de terceros que instales y verifica su estado y credibilidad.
No actualices a ciegas a las versiones nuevas; deja que circulen durante un tiempo antes de probarlas.
Antes de actualizar, revisa el registro de cambios y las notas de la versión que vas a instalar.
Al instalar paquetes, agrega el sufijo
--ignore-scriptspara desactivar la ejecución de scripts de paquetes de terceros.Considera agregar
ignore-scriptsal archivo de proyecto.npmrco a la configuración global de npm.
4. Evalúa el estado del proyecto de npm
Dependencias desactualizadas
Apurarse a actualizar constantemente las dependencias a sus versiones más recientes no es necesariamente una buena práctica si no se revisan las notas de la versión y los cambios en el código, ni se prueban exhaustivamente las nuevas actualizaciones. Dicho esto, quedarse atrás y no actualizar nunca, o hacerlo después de mucho tiempo, también puede causar problemas.
La CLI de npm puede darte información sobre qué tan actualizadas están tus dependencias en relación con sus versiones semánticas. Si ejecutas npm outdated, puedes ver qué paquetes están desactualizados:

"Las dependencias en amarillo corresponden a las versiones semánticas especificadas en el manifiesto package.json; las dependencias en rojo indican que hay una actualización disponible. Además, el resultado también muestra la versión más reciente de cada dependencia.
Llama al doctor
Entre la variedad de administradores de paquetes de Node.js y las distintas versiones de Node.js que quizá tengas instaladas en tu ruta, ¿cómo puedes verificar que la instalación de npm y el entorno funcionen correctamente? Ya sea que trabajes con la CLI de npm en un entorno de desarrollo o en CI, es importante comprobar que todo funcione como se espera.
¡Llama al doctor! La CLI de npm incluye una herramienta de evaluación del estado que diagnostica tu entorno para comprobar que npm funcione correctamente. Ejecuta npm doctor para revisar tu configuración de npm:
Comprueba que se pueda acceder al registro oficial de npm y muestra el registro configurado actualmente.
Comprueba que Git esté disponible.
Revisa las versiones instaladas de npm y Node.js.
Comprueba los permisos de las distintas carpetas, como las de
node_moduleslocales y globales, y la carpeta que se usa para la caché de paquetes.Comprueba que las sumas de verificación de la caché local de módulos de npm sean correctas.
5. Audita las vulnerabilidades de las dependencias de código abierto
El ecosistema de npm es el mayor repositorio de bibliotecas de aplicaciones entre todos los ecosistemas de lenguajes. El registro y sus bibliotecas son fundamentales para los desarrolladores de JavaScript, ya que pueden aprovechar el trabajo que otras personas ya hicieron e incorporarlo en su código. Sin embargo, la adopción cada vez mayor de bibliotecas de código abierto en las aplicaciones también aumenta el riesgo de introducir vulnerabilidades de seguridad.
Se ha descubierto que muchos paquetes populares de npm son vulnerables y pueden representar un riesgo considerable si no se auditan correctamente las dependencias del proyecto. Algunos ejemplos son npm request, superagent, mongoose e incluso paquetes relacionados con la seguridad, como jsonwebtoken y npm validator.
La seguridad no consiste solo en buscar vulnerabilidades al instalar un paquete. Para que se adopte eficazmente durante todo el ciclo de vida del desarrollo de software, también debe integrarse en los flujos de trabajo de los desarrolladores y supervisarse continuamente cuando se implementa el código.
Analiza en busca de vulnerabilidades
Sigue las mejores prácticas de seguridad para npm y analiza en busca de vulnerabilidades con Snyk. Usa:
Al ejecutar una prueba de Snyk, Snyk informa las vulnerabilidades encontradas y muestra las rutas vulnerables para que puedas seguir el árbol de dependencias y entender qué módulo introdujo una vulnerabilidad. Lo más importante es que Snyk te ofrece recomendaciones prácticas para corregirlas: puedes actualizar a una versión corregida mediante un pull request automatizado que Snyk abre en tu repositorio, o aplicar un parche proporcionado por Snyk para mitigar la vulnerabilidad si no hay una solución disponible. Snyk recomienda una actualización inteligente a la versión semántica mínima necesaria del paquete vulnerable.
Supervisa las vulnerabilidades que se descubren en bibliotecas de código abierto
El trabajo de seguridad no termina ahí.
¿Qué pasa con las vulnerabilidades de seguridad que se encuentran en una dependencia de la aplicación después de implementarla? Ahí es donde cobran importancia la supervisión de seguridad y la integración estrecha con el ciclo de vida del desarrollo del proyecto.
Te recomendamos integrar Snyk con tu sistema de administración de código fuente (SCM), como GitHub o GitLab, para que Snyk supervise activamente tus proyectos y:
Abra automáticamente PR para actualizar o aplicar parches a las dependencias vulnerables
Analice y detecte vulnerabilidades en bibliotecas de código abierto que podría haber introducido un pull request
Si no puedes integrar Snyk con un SCM, también puedes supervisar instantáneas de tus proyectos enviadas desde la herramienta Snyk CLI. Solo tienes que ejecutar:
¿En qué se diferencia Snyk de npm audit?
Te invitamos a leer una publicación del blog de Nearform que compara las diferencias entre la auditoría de npm y Snyk.
La base de datos de vulnerabilidades de Snyk ofrece datos exhaustivos sobre vulnerabilidades mediante su sistema de inteligencia de amenazas. Brinda una mayor cobertura y permite detectar e informar vulnerabilidades que aún no tienen un CVE. Por ejemplo, el 72 % de las vulnerabilidades de los avisos de npm se agregó primero a la base de datos de vulnerabilidades de Snyk Open Source.
6. Usa un proxy local de npm
El registro de npm es la mayor colección de paquetes disponible para todos los desarrolladores de JavaScript y también alberga la mayoría de los proyectos de código abierto para desarrolladores web. Sin embargo, a veces puedes tener otras necesidades de seguridad, implementación o rendimiento. En esos casos, npm te permite cambiar a otro registro:
Cuando ejecutas npm install, se comunica automáticamente con el registro principal para resolver todas tus dependencias. Si quieres usar otro registro, también es muy sencillo:
Usa
npm set registrypara configurar un registro predeterminado.Usa el argumento
--registrypara especificar un solo registro.
Verdaccio es un registro privado sencillo y ligero que no requiere configuración. Instalarlo es así de fácil:

¡Nunca había sido tan fácil alojar tu propio registro! Veamos las funciones más importantes de esta herramienta:
Es compatible con el formato del registro de npm, incluidas las funciones para paquetes privados, la compatibilidad con ámbitos, el control de acceso a paquetes y la autenticación de usuarios en la interfaz web.
Permite conectar registros remotos y enrutar cada dependencia a distintos registros, además de almacenar archivos tar en caché. Para reducir las descargas duplicadas y ahorrar ancho de banda en tus servidores de desarrollo local y CI, deberías usar un proxy para todas las dependencias.
De forma predeterminada, usa htpasswd como proveedor de autenticación, pero también es compatible con Gitlab, Bitbucket y LDAP. También puedes usar tu propio proveedor.
Es fácil escalarlo con otro proveedor de almacenamiento.
Si tu proyecto se basa en Docker, usar la imagen oficial es la mejor opción.
Permite iniciar entornos de prueba muy rápido y es útil para probar proyectos de monorepositorios grandes.
Es bastante sencillo ejecutarlo:
Si usas verdaccio como registro privado local, considera configurar tus paquetes para que se publiquen en el registro local y evitar que los desarrolladores los publiquen por accidente en un registro público. Para hacerlo, agrega lo siguiente a package.json:
Tu registro ya está funcionando. ¡Sí! Ahora, para publicar un paquete, solo usa el comando de npm npm publish y estará listo para compartirlo con el mundo.
7. Divulga las vulnerabilidades de seguridad de forma responsable
Cuando se descubren vulnerabilidades de seguridad, pueden representar una amenaza grave si se divulgan públicamente sin aviso previo ni medidas de mitigación adecuadas que permitan a los usuarios protegerse.
Se recomienda que los investigadores de seguridad sigan un programa de divulgación responsable, es decir, un conjunto de procesos y pautas cuyo objetivo es conectar a los investigadores con el proveedor o responsable del activo vulnerable para comunicar la vulnerabilidad, su impacto y su aplicabilidad. Una vez que se haya evaluado correctamente la vulnerabilidad, el proveedor y el investigador coordinan una solución y una fecha de publicación para ofrecer una ruta de actualización o medidas de corrección a los usuarios afectados antes de hacer público el problema de seguridad.
La seguridad es demasiado importante como para dejarla para después o manejarla de forma poco ética. En Snyk, valoramos profundamente a la comunidad de seguridad y creemos que la divulgación responsable de las vulnerabilidades de seguridad en paquetes de código abierto nos ayuda a proteger la seguridad y la privacidad de los usuarios.
El equipo de investigación de seguridad de Snyk colabora regularmente con la comunidad en programas de recompensas por errores, como ocurrió con f2e-server, que dio lugar a cientos de divulgaciones de la comunidad. Además, Snyk mantiene una estrecha colaboración con investigadores académicos, como los de Virginia Tech, para aportar experiencia en seguridad y facilitar la coordinación con proveedores y responsables del mantenimiento de la comunidad.
Te invitamos a colaborar con nosotros. También podemos ayudarte con el proceso de divulgación:
Reporta divulgaciones de seguridad responsables en https://snyk.io/vulnerability-disclosure o por correo electrónico a security@snyk.io
Puedes consultar nuestra política de divulgación aquí.
8. Activa la autenticación de dos factores (2FA)
En octubre de 2017, npm anunció oficialmente que ofrecería autenticación de dos factores (2FA) a los desarrolladores que usan el registro de npm para alojar sus paquetes privados y de código abierto.
Aunque el registro de npm ofrece compatibilidad con 2FA desde hace tiempo, parece que su adopción ha sido lenta. Un ejemplo fue el incidente de eslint-scope de mediados de 2018, cuando el robo de la cuenta de un desarrollador del equipo de ESLint permitió a actores maliciosos publicar una versión maliciosa de eslint-scope.
** AVISO URGENTE DE SEGURIDAD ** Comparte esta información.
Hoy se descubrió que la versión 3.7.2 de eslint-scope (https://t.co/Gkc9XhDRN6) contiene código malicioso que roba tus credenciales de NPM. Si usas la versión 3.7.2, actúa ahora.
Entrada en la base de datos de Snyk: https://t.co/dAhhA3cZQP
— Snyk (@snyksec) 12 de julio de 2018
Activar 2FA es una forma sencilla y eficaz de mejorar las prácticas de seguridad de npm. El registro ofrece dos modalidades para activar 2FA en una cuenta:
Solo autorización: se solicita cuando un usuario inicia sesión en npm desde el sitio web o la CLI, o realiza otras acciones, como cambiar la información del perfil.
Autorización y escritura: se solicita para iniciar sesión y realizar acciones en el perfil, además de acciones de escritura, como administrar tokens y paquetes. También ofrece compatibilidad limitada con la información de visibilidad de equipos y paquetes.
Consigue una aplicación de autenticación, como Google Authentication, que puedes instalar en un dispositivo móvil, y ya podrás comenzar. Una forma sencilla de activar la protección adicional de 2FA en tu cuenta es usar la interfaz de npm, que permite hacerlo fácilmente. Si prefieres la línea de comandos, también puedes activar 2FA con una versión compatible del cliente de npm (>=5.5.1):
Sigue las instrucciones de la línea de comandos para activar 2FA y guardar los códigos de autenticación de emergencia. Si quieres activar 2FA solo para iniciar sesión y cambiar el perfil, puedes reemplazar auth-and-writes por auth-only en el código que aparece arriba.
9. Usa tokens de autor de npm
Cada vez que inicias sesión con la CLI de npm, se genera un token para tu usuario que te autentica en el registro de npm. Los tokens facilitan las acciones relacionadas con el registro de npm durante la CI y los procesos automatizados, como acceder a módulos privados en el registro o publicar versiones nuevas desde un paso de compilación.
Puedes administrar los tokens desde el sitio web del registro de npm o mediante el cliente de línea de comandos de npm. A continuación, se muestra un ejemplo de cómo usar la CLI para crear un token de solo lectura restringido a un rango específico de direcciones IPv4:
Para verificar qué tokens se crearon para tu usuario o revocarlos en caso de emergencia, puedes usar npm token list o npm token revoke, respectivamente.
Sigue esta práctica recomendada de seguridad de npm: protege tus tokens de npm y limita su exposición.
10. Comprende las convenciones para nombrar módulos y los ataques de typosquatting
Al crear un paquete, una de las primeras cosas que haces es ponerle un nombre. Pero antes de decidirte por uno, ten en cuenta que npm establece algunas reglas para los nombres de paquetes:
No puede superar los 214 caracteres
No puede comenzar con un punto ni un guion bajo
No puede contener letras mayúsculas
No puede terminar con espacios
Solo puede contener letras minúsculas
No se permiten algunos caracteres especiales: “~\’!()*”)’
No puede comenzar con . ni _
No puede llamarse node_modules ni favicon.ico, ya que esos nombres están prohibidos
Aunque sigas estas reglas, ten en cuenta que npm usa un mecanismo de detección de spam al publicar paquetes nuevos. Este se basa en una puntuación y en si el nombre del paquete infringe las condiciones del servicio. Si se incumplen las condiciones, es posible que el registro rechace la solicitud.
El typosquatting es un ataque que se aprovecha de errores de los usuarios, como los errores tipográficos. Mediante esta técnica, actores maliciosos pueden publicar módulos con nombres muy parecidos a los de módulos populares existentes en el registro de npm.
Hemos seguido la pista de decenas de paquetes maliciosos en el ecosistema de npm, que también se han detectado en el registro de Python PyPi. Algunos de los incidentes más conocidos afectaron a cross-env, event-stream y eslint-scope.

Uno de los principales objetivos de los ataques de typosquatting son las credenciales de usuario, ya que cualquier paquete puede acceder a las variables de entorno mediante la variable global process.env. Otro ejemplo que hemos visto es el caso de event-stream, en el que el ataque tenía como objetivo a los desarrolladores y buscaba inyectar código malicioso en el código fuente de una aplicación.
Para cerrar nuestra lista de diez prácticas recomendadas de seguridad de npm, te compartimos los siguientes consejos para reducir el riesgo de estos ataques:
Ten mucho cuidado al copiar y pegar instrucciones de instalación de paquetes en la terminal. Verifica que el paquete que quieres instalar sea el correcto, tanto en el repositorio de código fuente como en el registro de npm. Puedes verificar los metadatos del paquete con
npm infopara obtener más información sobre sus colaboradores y las versiones más recientes.Como práctica habitual, cierra la sesión de npm en tu rutina diaria de trabajo para que tus credenciales no sean el punto débil que permita comprometer tu cuenta fácilmente.
Al instalar paquetes, agrega
--ignore-scriptspara reducir el riesgo de ejecutar comandos arbitrarios. Por ejemplo:npm install my-malicious-package --ignore-scripts
Asegúrate de imprimir la guía rápida y colocarla en algún lugar visible para recordar algunas de las prácticas recomendadas de seguridad de npm que debes seguir si desarrollas en JavaScript o simplemente disfrutas usando npm.
Empieza con los desafíos de Capture the Flag
Aprende a resolver desafíos de captura la bandera con nuestro taller virtual introductorio a pedido.