
Um auxiliar local de instalação de pacotes confiava demais em nomes de pacotes fornecidos pelo chamador. No yeoman-environment, geradores ausentes podiam ser instalados sem confirmação do usuário, transformando metadados de projeto controlados por atacantes em um caminho de instalação de pacotes e execução de código.
Um auxiliar de instalação de pacotes local confiou excessivamente em nomes de pacotes fornecidos pelo chamador. No yeoman-environment, geradores ausentes podiam ser instalados sem confirmação do usuário, transformando metadados de projeto controlados por um atacante em um caminho de instalação de pacotes e execução de código.
Encontrei esse problema ao revisar o generator-jhipster com uma simples questão de segurança em mente:
Metadados de projeto controlados por um atacante podem fazer com que uma ferramenta de desenvolvimento busque e execute código de terceiros antes que o usuário solicite explicitamente isso?
Neste caso, a resposta foi sim.
O que inicialmente parecia ser um problema do JHipster acabou tendo uma causa raiz upstream mais profunda no yeoman-environment.
O comportamento vulnerável estava no fluxo de instalação local de geradores do Yeoman, onde pacotes ausentes fornecidos pelo chamador eram instalados automaticamente sem confirmação do usuário. Em um consumidor downstream que passava nomes de pacotes controlados pelo atacante para esse caminho, isso era suficiente para criar uma cadeia real de instalação de pacotes e execução de código.
Esse problema se tornou CVE-2026-42089.
yeoman-environment: yeoman-environment no GitHub
Pacote: yeoman-environment (npm)
CVE: CVE-2026-42089
Isso afetou o yeoman-environment, a camada de runtime por trás do fluxo de carregamento e inicialização de geradores do Yeoman. O projeto oficial descreve-o como o componente que gerencia o ciclo de vida e a descoberta de geradores e, em 26 de junho de 2026, a página do pacote npm listava , tornando este um pacote amplamente implantado no ecossistema de ferramentas JavaScript.

configuração de projeto controlada pelo atacante -> nomes de geradores fornecidos pelo chamador -> yeoman-environment instala pacotes ausentes silenciosamente -> ferramenta downstream carrega código do gerador instalado -> instalação de pacote e execução de código durante a inicialização da CLI
O yeoman-environment é a camada de runtime e carregamento de geradores por trás das ferramentas baseadas no Yeoman.
Entre outras coisas, ele lida com:
Isso significa que ele está diretamente em um limite de confiança.
A questão relevante não é se o Yeoman é "apenas uma ferramenta local".
A questão relevante é se entrada não confiável pode influenciar o comportamento de instalação de pacotes e carregamento de código.
Neste caso, podia.
Eu não estava procurando por corrupção de memória ou bugs que causam apenas quedas.
O alvo mais forte era a superfície de extensão e resolução de pacotes.
Qualquer sistema que:
merece um exame cuidadoso.
Isso é especialmente verdadeiro quando o consumidor downstream pode derivar esses nomes de pacotes a partir de dados locais do projeto.
Este é exatamente o tipo de lugar onde uma configuração comum pode silenciosamente se tornar um limite de segurança.
Esse era o lugar certo para procurar.
Primeiro reproduzi o comportamento através do generator-jhipster.
O caminho importante era:
.yo-rc.json declara um pacote blueprintIsso significava que mesmo um comando benigno como:
jhipster --help
podia alcançar a instalação de pacotes antes que o comando solicitado fosse concluído.
Isso é uma verdadeira falha de limite de confiança.
O gatilho downstream ajudou a expô-lo, mas o comportamento padrão inseguro estava no Yeoman.
O bug era simples.
No yeoman-environment, o método vulnerável 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;
}
Esse método instalava nomes de pacotes fornecidos pelo chamador diretamente através de:
this.repository.install(specs)
sem solicitar confirmação ao usuário primeiro.
Essa é a vulnerabilidade central.
Porque os nomes dos pacotes não precisam vir de uma fonte confiável.
Se um consumidor downstream os deriva de metadados de projeto controlados pelo atacante, então a cadeia de exploração é direta:
Isso não é apenas "instalação de pacote ocorreu".
Isso é entrada não confiável cruzando para um sink de instalação de pacotes sem um limite de consentimento explícito.
A distinção importante é a instalação silenciosa a partir de entrada não confiável.
Há uma diferença real entre:
Essa distinção importa ainda mais quando o pacote se torna carregável imediatamente depois.
O problema não era que geradores de terceiros existem.
O problema era que o Yeoman tratava nomes de pacotes fornecidos pelo chamador como instaláveis por padrão, sem confirmação do usuário.
Isso torna suposições de confiança downstream inseguras materialmente piores.
É exatamente por isso que a correção adicionou uma etapa de confirmação.
Usei duas camadas de prova porque demonstraram tanto a causa raiz quanto o impacto real downstream.
A primeira prova usou o generator-jhipster não modificado.
Criei um projeto com um .yo-rc.json raiz que referenciava um pacote blueprint que não estava instalado, e executei:
jhipster --help
Isso fez com que o JHipster passasse o blueprint ausente para o fluxo de instalação local de geradores do Yeoman antes que a ajuda fosse concluída.
O resultado importante foi:
Isso estabeleceu claramente a condição real do gatilho.
A segunda prova usou um registro local controlado e um pacote projetado para demonstrar efeitos colaterais no momento da importação de forma segura.
Isso foi importante porque queria mostrar a história mais forte:
Esta foi a cadeia de evidências mais forte porque moveu o problema além de:
"tentativa de instalação inesperada"
e para:
"caminho de instalação mais carregamento de código downstream é realmente alcançável"
Esse é o ponto em que a falha de limite de confiança se torna muito mais difícil de descartar.
O primeiro PoC prova o comportamento de instalação silenciosa.
O segundo PoC prova por que esse comportamento importa.
Essa divisão foi importante.
Um relatório que para em:
"um pacote pode ser instalado"
é mais fraco do que um relatório que mostra:
Essa é a história completa.
Durante o tratamento do advisory e a revisão local, o comportamento foi rastreado até a introdução de installLocalGenerators() em:
yeoman-environment 2.9.0
A faixa afetada era, portanto:
>= 2.9.0 e < 6.0.1
A versão corrigida era:
6.0.1
A correção foi correta e mínima.
Na 6.0.1, installLocalGenerators() foi alterado para adicionar uma etapa de confirmação antes da instalação, a menos que a instalação forçada seja explicitamente solicitada.
A forma corrigida se parecia com:
async installLocalGenerators(packages, forceInstall = false) {
e depois:
const { aproveInstall } = await this.adapter.prompt({
message: `Os seguintes pacotes precisam ser instalados no repositório local: ${specs.join(', ')}. Deseja continuar?`,
type: 'confirm',
name: 'aproveInstall',
default: false,
});
Se o usuário recusar, a instalação é abortada.
Essa é a correção certa porque restaura o limite de confiança ausente:
Esta correção foi implementada em:
78d2af7
através de:
PR #753
Esse é exatamente o tipo de remediação que você deseja em um problema de segurança como este:
Este problema foi razoavelmente levado a sério porque o impacto é mais do que cosmético ou comportamento surpreendente.
O comportamento vulnerável pode levar a:
O vetor CVSS associado ao problema foi:
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H
Isso faz sentido para a história de exploração downstream:
Este problema começou como um relatório privado contra o generator-jhipster, porque esse era o caminho de gatilho do mundo real que inicialmente validei.
Durante a triagem, os mantenedores do JHipster apontaram que o comportamento de instalação automática estava no yeoman-environment e referenciaram a correção upstream.
Isso levou ao pivô correto:
Os mantenedores do Yeoman revisaram o problema, confirmaram a faixa afetada e o rastrearam através de um advisory privado.
O relatório foi posteriormente atribuído a:
CVE-2026-42089
Esse advisory também documentou o caminho de gatilho downstream real através do generator-jhipster.
Este foi um bom exemplo de por que a divulgação coordenada às vezes precisa de uma etapa extra:
Aqui, a reprodução downstream foi útil, mas o pacote upstream era o lugar certo para o CVE.
A lição chave aqui é simples:
instalação de pacotes é um limite de segurança, mesmo em ferramentas de desenvolvimento locais
Muitas pessoas instintivamente rebaixam problemas como este porque ocorrem em ferramentas CLI.
Isso é um erro.
A questão real não é se a ferramenta é local.
A questão real é:
A entrada não confiável pode fazer a ferramenta buscar e confiar em código sem uma decisão explícita do usuário?
Neste caso, sim.
Essa é a verdadeira lição.
Este problema também reforça algo importante sobre boa pesquisa de vulnerabilidades:
Esse foi exatamente o formato deste CVE.
Esta vulnerabilidade não era sobre um payload chamativo.
Era sobre fazer a pergunta certa sobre limite de confiança.
Uma ferramenta downstream permitiu que dados locais do projeto influenciassem a seleção de pacotes. O Yeoman instalou o pacote ausente sem confirmação. O restante da cadeia de carregamento de código fez o resto.
É por isso que isso se tornou CVE-2026-42089.
Corrigido no yeoman-environment 6.0.1.