Un asistente de instalación local de paquetes confiaba demasiado en los nombres de paquetes proporcionados por el llamante. En yeoman-environment, los generadores faltantes podían instalarse sin confirmación del usuario, convirtiendo los metadatos del proyecto controlados por el atacante en una ruta de instalación de paquetes y ejecución de código.
Un ayudante de instalación de paquetes local confiaba demasiado en los nombres de paquetes proporcionados por el llamante. En yeoman-environment, los generadores faltantes podían instalarse sin confirmación del usuario, convirtiendo metadatos de proyecto controlados por un atacante en una ruta de instalación de paquetes y ejecución de código.
Encontré este problema al revisar generator-jhipster con una simple pregunta de seguridad en mente:
¿Pueden los metadatos de proyecto controlados por un atacante hacer que una herramienta de desarrollo obtenga y ejecute código de terceros antes de que el usuario lo haya solicitado explícitamente?
En este caso, la respuesta fue sí.
Lo que inicialmente parecía un problema de JHipster resultó tener una causa raíz más profunda en yeoman-environment.
El comportamiento vulnerable estaba en el flujo de instalación de generadores locales de Yeoman, donde los paquetes faltantes suministrados por el llamante se instalaban automáticamente sin confirmación del usuario. En un consumidor downstream que pasaba nombres de paquetes controlados por un atacante a esa ruta, eso era suficiente para crear una cadena real de instalación de paquetes y ejecución de código.
Ese problema se convirtió en CVE-2026-42089.
yeoman-environment: yeoman-environment en GitHub
Paquete: yeoman-environment (npm)
CVE: CVE-2026-42089
Esto afectó a yeoman-environment, la capa de ejecución detrás del flujo de carga e inicio de generadores de Yeoman. El proyecto oficial lo describe como el componente que maneja el ciclo de vida y el descubrimiento de generadores, y al 26 de junio de 2026, la página del paquete npm mostraba 1,466,426 descargas semanales, lo que lo convierte en un paquete ampliamente desplegado en el ecosistema de herramientas JavaScript.
configuración de proyecto controlada por atacante -> nombres de paquetes generador proporcionados por el llamante -> yeoman-environment instala silenciosamente paquetes faltantes -> herramienta downstream carga el código del generador instalado -> instalación de paquetes y ejecución de código durante el arranque del CLI
yeoman-environment es la capa de ejecución y carga de generadores detrás de las herramientas basadas en Yeoman.
Entre otras cosas, maneja:
Eso significa que se encuentra directamente en un límite de confianza.
La pregunta relevante no es si Yeoman es "solo una herramienta local".
La pregunta relevante es si la entrada no confiable puede influir en el comportamiento de instalación de paquetes y carga de código.
En este caso, podía.
No estaba buscando corrupción de memoria o errores que solo causaran caídas aquí.
El objetivo más fuerte era la superficie de extensión y resolución de paquetes.
Cualquier sistema que:
merece un escrutinio cercano.
Esto es especialmente cierto cuando el consumidor downstream puede derivar esos nombres de paquetes de datos locales del proyecto.
Este es exactamente el tipo de lugar donde la configuración ordinaria puede convertirse silenciosamente en un límite de seguridad.
Ese era el lugar adecuado para mirar.
Primero reproduje el comportamiento a través de generator-jhipster.
La ruta importante era:
.yo-rc.json local del proyecto declara un paquete blueprintEso significaba que incluso un comando benigno como:
jhipster --help
podía llegar a la instalación de paquetes antes de que el comando solicitado se completara.
Eso es una falla real del límite de confianza.
El desencadenante downstream ayudó a exponerlo, pero el comportamiento predeterminado inseguro estaba en Yeoman.
El error era simple.
En yeoman-environment, el método vulnerable era:
async installLocalGenerators(packages) {
const entries = Object.entries(packages);
const specs = entries.map(([packageName, version]) => `${packageName}${version ? `@${version}` : ''}`);
const installResult = await this.repository.install(specs);
const failToInstall = installResult.find(result => !result.path);
if (failToInstall) {
throw new Error(`Fail to install ${failToInstall.pkgid}`);
}
await this.lookup({ packagePaths: installResult.map(result => result.path) });
return true;
}
Ese método instalaba nombres de paquetes proporcionados por el llamante directamente a través de:
this.repository.install(specs)
sin preguntar primero al usuario.
Esa es la vulnerabilidad central.
Porque los nombres de paquetes no tienen que provenir de una fuente confiable.
Si un consumidor downstream los deriva de metadatos de proyecto controlados por un atacante, entonces la cadena de explotación es directa:
Eso no es solo "la instalación del paquete ocurrió".
Eso es entrada no confiable cruzando hacia un sumidero de instalación de paquetes sin un límite de consentimiento explícito.
La distinción importante es la instalación silenciosa desde entrada no confiable.
Hay una diferencia real entre:
Esa distinción importa aún más cuando el paquete se vuelve cargable inmediatamente después.
El problema no era que existieran generadores de terceros.
El problema era que Yeoman trataba los nombres de paquetes proporcionados por el llamante como instalables por defecto sin confirmación del usuario.
Eso empeora materialmente las suposiciones de confianza downstream inseguras.
Es exactamente por eso que la corrección añadió una puerta de confirmación.
Usé dos capas de prueba porque demostraban tanto la causa raíz como el impacto real downstream.
La primera prueba usó generator-jhipster sin modificar.
Creé un proyecto con un .yo-rc.json raíz que referenciaba un paquete blueprint que no estaba instalado, luego ejecuté:
jhipster --help
Eso hizo que JHipster pasara el blueprint faltante al flujo de instalación de generadores locales de Yeoman antes de que la ayuda se completara.
El resultado importante fue:
Eso estableció claramente la condición de activación real.
La segunda prueba usó un registro local controlado y un paquete diseñado para demostrar efectos secundarios en tiempo de importación de manera segura.