El ecosistema de paquetes de JavaScript, particularmente npm, siempre ha sido una frontera vibrante, aunque ocasionalmente caótica. Pero a medida que cerramos 2025, el ambiente está cargado de un tipo diferente de energía: un impulso palpable y urgente hacia una cadena de suministro de software más segura. Los recientes ataques de alto perfil han cambiado la conversación de "si" a "cómo" fortalecemos colectivamente nuestras dependencias. He estado en las trincheras, probando las últimas herramientas y observando cómo evoluciona el panorama, y honestamente, algunos de los avances son genuinamente impresionantes, aunque el camino hacia la adopción completa todavía esté lleno de algunas espinas molestas.
Esto no se trata solo de parches; es una reevaluación fundamental de la confianza, la procedencia y la mecánica misma de cómo consumimos y publicamos código. La buena noticia es que estamos viendo esfuerzos reales y tangibles por parte del equipo central de npm, GitHub y la comunidad en general para abordar estas vulnerabilidades sistémicas.
El auge de npm provenance y Sigstore: Confianza en la fuente
Esto es genuinamente impresionante porque aborda una de las amenazas más insidiosas: un entorno de compilación o publicación comprometido. Durante años, hemos confiado en el campo integrity de package.json para las sumas de comprobación, pero eso solo verifica el paquete descargado contra lo que el registro cree que debería ser. No nos dice si el paquete fue construido y publicado por el mantenedor legítimo en un entorno confiable. Aquí es donde entra npm provenance, disponible generalmente desde octubre de 2023, con un impulso significativo a lo largo de 2024 y 2025.
npm provenance es la implementación de npm del marco de niveles de la cadena de suministro para artefactos de software (SLSA), aprovechando el poder de Sigstore. La idea central es crear atestaciones verificables sobre cómo y dónde se construyó y publicó un paquete. Cuando publicas un paquete con --provenance, la CLI de npm trabaja con tu proveedor de CI/CD (actualmente GitHub Actions y GitLab CI/CD son compatibles) para generar una atestación de procedencia. Esta atestación incluye detalles como la URI del repositorio de origen, el hash del commit y las instrucciones de compilación.
Aquí está la elegancia arquitectónica: en lugar de administrar claves de firma de larga duración, Sigstore utiliza certificados efímeros de corta duración emitidos por una Autoridad de Certificación (Fulcio) que se federan con tu proveedor de OIDC. Este certificado se utiliza luego para firmar la declaración de procedencia, y tanto el certificado como la firma se registran en un registro de transparencia público e inmutable (Rekor). Esto significa que firmas la compilación, descartas la clave privada y todo el proceso es auditable públicamente.
Para publicar con procedencia, es tan simple como agregar una bandera:
npm publish --provenance --access public
¿Y para la verificación? El comando npm audit signatures, introducido en julio de 2022, es ahora nuestro mejor amigo para esto. Verifica las firmas ECDSA y mostrará un error si los paquetes tienen firmas faltantes o inválidas, lo que indica una posible manipulación.
npm audit signatures
Este es un paso monumental hacia adelante. Si bien no garantiza la ausencia de código malicioso, proporciona un vínculo criptográfico con la fuente y el entorno de compilación, lo que permite a los desarrolladores tomar decisiones de confianza informadas. La limitación, por ahora, es su dependencia de los runners alojados en la nube y proveedores de CI/CD específicos. Para aquellos de nosotros con runners auto-hospedados o sistemas de CI alternativos, la adopción aún es un poco engorrosa, lo que requiere soluciones manuales o esperar un soporte más amplio. Pero la dirección es clara y es robusta.
Fortaleciendo al publicador: 2FA, tokens granulares y publicación confiable
La oleada de ataques a la cadena de suministro en 2025, incluido el gusano "Shai-Hulud" en septiembre y las posteriores campañas de typosquatting en octubre, sirvió como una dura llamada de atención. Los atacantes comprometieron las cuentas de los mantenedores a través de phishing sofisticado, lo que llevó a la inyección de paquetes maliciosos. GitHub, que es propietaria de npm, ha respondido con cambios agresivos y necesarios a la autenticación y publicación, implementados en gran medida entre octubre y mediados de noviembre de 2025.
Los cambios clave son:
- 2FA obligatorio para la publicación local: Esta es una gran victoria. Ya no se puede publicar desde una máquina local solo con una contraseña. Si estás publicando desde tu entorno de desarrollo, se requerirá 2FA. Esto aborda directamente los vectores de phishing que plagaron a los mantenedores.
- Deprecación de los tokens clásicos heredados: Los tokens npm clásicos, a menudo de larga duración y de amplio alcance, están siendo eliminados gradualmente. Esto es crítico porque los tokens de larga duración comprometidos fueron un vector de ataque principal.
- Vida útil limitada para los tokens granulares: Los nuevos tokens granulares, que permiten permisos más específicos, tendrán una vida útil máxima de siete días (con un máximo de 90 días para algunos casos). Esto reduce drásticamente la ventana de oportunidad para los atacantes si se roba un token.
- Expansión de la publicación confiable: El soporte de npm para la publicación confiable, introducido en julio de 2025, elimina la necesidad de administrar tokens de API en los sistemas de CI/CD por completo. En cambio, los proveedores de CI/CD (como GitHub Actions) pueden atestiguar directamente la identidad del publicador, y npm verifica esta atestación. Este es el estándar de oro, ya que elimina el token como secreto en tu canalización de compilación.
La transición, aunque necesaria, ha causado algunas interrupciones en el flujo de trabajo para los desarrolladores acostumbrados a las prácticas más antiguas. La depreciación de 2FA TOTP a favor de 2FA basado en FIDO (como WebAuthn/passkeys) también es un movimiento significativo, ya que la autenticación resistente al phishing es demostrablemente superior a TOTP contra ataques sofisticados. Si bien algunos desarrolladores pueden encontrar desafiante el cambio a passkeys debido a la compatibilidad de los dispositivos, los beneficios de seguridad son innegables.
Para aquellos que publican desde CI, la recomendación es usar npm publish --provenance con la configuración de Publicadores confiables, evitando por completo la necesidad de tokens explícitos en tu entorno de CI. Para la publicación local, asegúrate de que tu 2FA esté actualizado y sea resistente al phishing.
Más allá de npm audit: El panorama en evolución del escaneo de dependencias
npm audit ha sido un elemento básico desde 2018, haciendo un buen trabajo al marcar las vulnerabilidades conocidas en tu árbol de dependencias al verificar la Base de datos de avisos públicos de npm. Y si bien es una forma rápida y integrada de identificar problemas, los eventos recientes han resaltado sus limitaciones. Un npm audit solo funciona contra vulnerabilidades conocidas. No detecta malware novedoso, ataques sutiles a la cadena de suministro que modifican paquetes legítimos o vulnerabilidades en tu propio código.
El gusano "Shai-Hulud", por ejemplo, comprometió paquetes y los republicó con malware. Si bien npm audit podría eventualmente detectar las nuevas versiones maliciosas si se publican avisos, la propagación inicial puede ser rápida. Esto subraya la necesidad de un enfoque de múltiples capas.
Aquí es donde las herramientas especializadas realmente brillan. Soluciones como Snyk y SonarQube profundizan mucho más. Snyk, por ejemplo, ofrece detección de vulnerabilidades en tiempo real en las dependencias, monitoreo continuo e incluso solicitudes de extracción automatizadas para aplicar correcciones. SonarQube, si bien es más amplio en alcance para la calidad del código, también proporciona un análisis de seguridad integral para JavaScript y Node.js, capaz de interrumpir las compilaciones si no se cumplen los umbrales de seguridad.
Integrar estas herramientas en las canalizaciones de CI/CD ya no es un "agradable tener" sino un "imprescindible". Una configuración típica podría implicar:
- Ganchos pre-commit: Ejecutar linters básicos y análisis estático para detectar problemas obvios desde el principio.
- Paso de compilación de CI: Ejecutar
npm auditpara una verificación rápida, pero lo más importante, integrar una herramienta SCA (Análisis de composición de software) robusta como Snyk o una herramienta SAST (Análisis estático de seguridad de aplicaciones) como SonarQube. - Monitoreo posterior al despliegue: Escanear continuamente las aplicaciones implementadas y sus dependencias en busca de vulnerabilidades recién descubiertas.
La realidad es que, si bien npm audit es accesible, es una línea de base. Confiar únicamente en él en 2025 es como llevar un cuchillo de mantequilla a un tiroteo. Las herramientas comerciales y de código abierto avanzadas, aunque requieren más configuración y potencialmente costo, ofrecen la profundidad necesaria para asegurar verdaderamente las aplicaciones modernas.
Seguridad en tiempo de ejecución reimaginada: los permisos de Deno y la visión de JSR
Si bien npm es el administrador de paquetes dominante para Node.js, el ecosistema JavaScript más amplio está viendo una fascinante evolución en los tiempos de ejecución, con Deno y Bun desafiando la hegemonía de Node.js. Lo emocionante es cómo sus filosofías están influyendo en la seguridad. Comprender las diferencias entre Node.js, Deno, Bun en 2025: Elegir tu tiempo de ejecución de JavaScript ahora es un requisito previo para una arquitectura segura.
Deno: Seguridad primero por defecto
Deno, creado por el fundador de Node.js Ryan Dahl, tiene la seguridad integrada en su núcleo. A diferencia de Node.js, que otorga a los scripts acceso irrestricto al sistema por defecto, Deno opera con un modelo de permisos aislado. Esto significa que un script de Deno no puede acceder al sistema de archivos, la red o las variables de entorno sin un permiso explícito.
Por ejemplo, para permitir el acceso a la red y leer del sistema de archivos, ejecutarías tu script de Deno con banderas:
deno run --allow-net --allow-read app.ts
Este modelo de permisos explícito es un cambio de juego para prevenir ataques a la cadena de suministro, donde los paquetes maliciosos a menudo intentan exfiltrar datos o comprometer el sistema host. Si un dependencia comprometida intenta fetch datos de un dominio no autorizado o read archivos confidenciales, Deno simplemente lo denegará, a menos que hayas otorgado explícitamente ese permiso.
JSR: Un nuevo registro para JavaScript moderno
Introducido en beta pública en marzo de 2024, JSR (JavaScript Registry) es la respuesta de Deno a un registro de paquetes moderno. JSR no pretende bifurcar npm sino construir sobre su éxito, adoptando ESM, soporte nativo de TypeScript y un enfoque en la seguridad y la experiencia del desarrollador.
Una de las características de seguridad destacadas de JSR es la "publicación segura y sin tokens". Similar a la publicación confiable de npm, JSR tiene como objetivo proteger contra los ataques a la cadena de suministro al eliminar la necesidad de tokens de larga duración durante el proceso de publicación. JSR también se centra en la procedencia completa de los paquetes publicados, lo que garantiza información de compilación verificable.
Bun: Velocidad con seguridad en evolución
Bun, el nuevo chico en el bloque construido en Zig, prioriza la velocidad pura en todos los aspectos: tiempo de ejecución, instalación de paquetes, agrupación y pruebas. Si bien Bun es increíblemente rápido y ofrece compatibilidad con npm, su modelo de seguridad es actualmente más similar a Node.js, con acceso irrestricto por defecto.
Sin embargo, el rápido ciclo de desarrollo de Bun sugiere que es posible que se incluyan características de seguridad más explícitas en la hoja de ruta. Por ahora, si aprovechas el increíble rendimiento de Bun, es crucial reforzar tu seguridad con un escaneo de dependencias robusto y salvaguardias de CI/CD, ya que su aislamiento nativo no es tan maduro como el de Deno.
El papel crucial de package-lock.json y SRI: Integridad que no puedes ignorar
El archivo package-lock.json es mucho más que una simple lista de versiones fijadas; es un manifiesto criptográfico de tu árbol de dependencias. Su campo integrity, específicamente, contiene un hash de integridad de subrecursos (SRI), típicamente SHA512, para cada paquete. Este hash es una huella digital única del contenido del paquete tal como se publicó originalmente en el registro.
Cuando ejecutas npm install (o npm ci en CI/CD, que se recomienda encarecidamente para la reproducibilidad), npm descarga el paquete, recalcula su hash y lo compara con el valor integrity en tu package-lock.json. Si no coinciden, la instalación falla, lo que indica una posible manipulación. Esta es nuestra primera y, a menudo, más crítica línea de defensa contra los actores maliciosos que modifican los paquetes en el registro o durante el tránsito.
Sin embargo, este mecanismo no es a prueba de todos los ataques a la cadena de suministro. El vector de ataque "envenenamiento del archivo de bloqueo" demuestra esto: si un atacante obtiene el control de la cuenta de un mantenedor, puede publicar una versión maliciosa de un paquete y luego actualizar el package-lock.json en el repositorio legítimo con el hash de integridad nuevo, malicioso. Si este package-lock.json comprometido se confirma y luego se ejecuta npm install o npm ci, el paquete malicioso se instalará porque el hash de integridad coincide con la versión del atacante.
Es por eso que npm provenance es tan crucial como una capa de defensa adicional, que demuestra quién publicó el paquete y cómo se construyó. Agrega una "fuente de verdad" más allá del simple hash.
Los desarrolladores siempre deben:
- Confirmar
package-lock.json: Esto garantiza instalaciones deterministas y proporciona los hashes de integridad para la verificación. - Revisar las diferencias de
package-lock.jsonen las PR: Busca cambios inesperados, especialmente en las versiones de los paquetes o los hashes de integridad, lo que podría indicar un actor malicioso que intenta inyectar una dependencia comprometida. - Asegurarse de que se use SHA-512: Los archivos
package-lock.jsonmás antiguos pueden usar SHA-1, que es criptográficamente débil y vulnerable a ataques de colisión. Las versiones modernas de npm usan SHA-512 por defecto, pero si estás en un proyecto más antiguo, una instalación nueva después de eliminarnode_modulesypackage-lock.json(y luego confirmar la nueva) puede actualizar estos hashes.
# Para forzar la actualización a SHA512 (¡usar con precaución, confirmar los cambios después!)
rm -rf node_modules package-lock.json
npm install
Defendiendo contra los ataques de scripts del ciclo de vida: La amenaza silenciosa
Una de las características más poderosas (y peligrosas) de los paquetes npm son los scripts del ciclo de vida. Estos son comandos de shell arbitrarios definidos en package.json (por ejemplo, preinstall, install, postinstall, prepack, prepare) que se ejecutan en varias etapas del proceso de instalación o publicación del paquete. Si bien son increíblemente útiles para la compilación, la configuración o la compilación de módulos nativos, también son un vector principal para los ataques a la cadena de suministro.
Un script postinstall malicioso, por ejemplo, puede ejecutar código arbitrario en la máquina de un usuario inmediatamente después de instalarse un paquete. Esto podría variar desde robar variables de entorno y credenciales hasta instalar malware adicional. Los ataques de typosquatting de octubre de 2025, que utilizaron infostealers de varias etapas y lanzaron terminales ocultos para extraer contraseñas del sistema y cookies del navegador, aprovecharon en gran medida los scripts postinstall.
Defenderse de esto requiere un enfoque de múltiples capas:
- Flag
--ignore-scripts: Para implementaciones de producción o al auditar nuevas dependencias, ejecutarnpm install --ignore-scriptspuede evitar que se ejecuten estos scripts. Esta es una salvaguarda crucial, especialmente en los entornos de CI/CD donde deseas minimizar la superficie de ejecución.npm install --ignore-scripts # O a través de una variable de entorno para un efecto global NPM_CONFIG_IGNORE_SCRIPTS=true npm install - Revisión cuidadosa de
package.json: Al agregar nuevas dependencias, siempre inspecciona supackage.jsonen busca de scripts del ciclo de vida sospechosos. Si un paquete de utilidad simple tiene un scriptpostinstallcomplejo, es una señal de alerta. - Entornos aislados: Ejecutar
npm installdentro de entornos o contenedores aislados puede limitar el radio de explosión de un script malicioso. - Análisis estático: Las herramientas de seguridad avanzadas a menudo pueden detectar patrones sospechosos en los scripts del ciclo de vida.
El camino por delante: Un ecosistema más resiliente
Mirando hacia atrás a 2024 y 2025, está claro que el ecosistema de paquetes de JavaScript ha pasado por momentos difíciles, pero está emergiendo más fuerte. Los recientes ataques, aunque dolorosos, han acelerado la adopción de características de seguridad críticas. Nos estamos moviendo hacia:
- Identidad y procedencia más sólidas:
npm provenancey Sigstore son un cambio de juego, que ofrecen vínculos verificables desde el paquete publicado hasta la fuente y la compilación. Esto cambia la confianza de "Espero que esto sea bueno" a "Puedo verificar que esto se construyó como se esperaba". - Flujos de publicación reforzados: 2FA obligatorio, tokens de corta duración y publicación confiable están dificultando significativamente que los atacantes comprometan las cuentas de los mantenedores e inyecten código malicioso. Esta es una defensa práctica y sólida contra el phishing.
- Escaneo sofisticado: Si bien
npm auditsigue siendo útil, la creciente dependencia de las herramientas SCA y SAST avanzadas, integradas profundamente en el SDLC, es crucial para detectar tanto las amenazas conocidas como las nuevas. - Seguridad en tiempo de ejecución: El modelo de permisos de seguridad integrado de Deno y el registro JSR centrado en la seguridad están superando los límites de lo posible en un entorno JavaScript seguro. Estos no son solo "alternativas" sino "innovaciones" que influirán en todo el ecosistema.
Sin embargo, aún no estamos fuera de peligro. La enorme escala del ecosistema npm (4,5 billones de solicitudes solo en 2024) lo convierte en un objetivo principal. La adopción de estas nuevas características de seguridad no es universal, y los proyectos heredados seguirán presentando desafíos. La experiencia del desarrollador aún puede ser engorrosa al integrar nuevas medidas de seguridad, y la documentación de algunas características experimentales (como el modelo de permisos experimental de Node.js, que aún está en evolución) puede ser escasa.
Mi opinión: adopta estos cambios con entusiasmo. Integra npm publish --provenance en tu CI/CD. Exige 2FA resistente al phishing para tu equipo. No solo ejecutes npm audit; invierte en un escaneo más profundo. Examina package-lock.json y piensa dos veces antes de habilitar los scripts del ciclo de vida de fuentes desconocidas. El ecosistema JavaScript es más resistente que nunca, pero su fuerza depende en última instancia de nuestra vigilancia colectiva y de nuestra disposición a adoptar estas medidas de seguridad prácticas y eficientes. Estamos construyendo el futuro y hacer que sea seguro es nuestra responsabilidad compartida.
Fuentes
🛠️ Herramientas relacionadas
Explora estas herramientas de DataFormatHub relacionadas con este tema:
- Formateador JSON - Formatea package.json
- Generador de hash - Verifica la integridad del paquete
