Português (Brasil)
  • pnpm
  • segurança
  • dependências
  • npm
  • yarn

Atualize dependências transitivas com PNPM: Corrija as vulnerabilidades de segurança sem quebrar nada

Corrigir vulnerabilidades de segurança pode ser uma tarefa frustrante, especialmente quando envolve dependências transitivas. Aprenda como atualizá-las sem afetar suas dependências diretas.

Gao
Gao
Founder

Atualmente, vulnerabilidades de segurança são um problema comum no desenvolvimento de software. Felizmente, temos ferramentas como GitHub Dependabot para nos ajudar a manter nossas dependências atualizadas com detecção automática e pull requests.

Dependabot

No entanto, nem sempre funciona como esperado. Como algumas dependências são transitivas, atualizá-las pode ser uma tarefa difícil para essas ferramentas, pois elas não sabem o impacto das mudanças e o que decidir fazer em caso de conflitos. Precisamos lidar com esses casos manualmente.

Métodos que não funcionam

  • Comandos oficiais como pnpm up irão bagunçar seu arquivo pnpm-lock.yaml. Há um problema sobre isso que ainda está aberto no momento em que este artigo foi escrito.
  • Instalar a versão mais recente da dependência direta que possui a dependência transitiva desejada pode não funcionar. Se a dependência direta não atualizou as definições de versão, a dependência transitiva não será atualizada, pois já foi resolvida e travada no arquivo pnpm-lock.yaml.

A solução

O campo overrides é um recurso poderoso no PNPM que permite substituir algumas resoluções de versão. Vamos usar esse recurso para atualizar dependências transitivas e fazer a mudança da forma mais mínima possível.

Vamos usar o alerta do Dependabot mencionado acima como exemplo. Ele nos informa que o pacote follow-redirects tem uma vulnerabilidade de segurança, e a versão corrigida é 1.15.6. No entanto, a dependência direta gatsby usa axios, que depende de [email protected].

Passo 1: Encontrar a dependência transitiva

Existem muitas maneiras de localizar a dependência transitiva, mas eu recomendaria a maneira mais direta: pesquisar no arquivo pnpm-lock.yaml.

E quanto ao "pnpm why"?

O comando pnpm why <package> é realmente útil. No entanto, ele pode confundir você nesse caso. Por exemplo, quando eu executo pnpm why follow-redirects, aqui está uma parte da saída:

Na verdade, há apenas uma resolução para follow-redirects no arquivo pnpm-lock.yaml. O comando pnpm why pode mostrar vários caminhos que dependem da mesma versão do pacote.

Passo 2: Adicione os overrides

O caso mais fácil é quando existe apenas uma resolução no arquivo pnpm-lock.yaml. Você pode adicionar a substituição diretamente ao arquivo package.json:

Se você estiver em um workspace, deve adicionar o override ao arquivo package.json da raiz do workspace.

Passo 3: Aplique as mudanças

Execute pnpm install para aplicar as mudanças. Podemos ver que o pacote follow-redirects foi atualizado para 1.15.6 no arquivo pnpm-lock.yaml com mudanças mínimas.

Agora você pode remover o campo overrides do arquivo package.json para mantê-lo limpo. Em seguida, execute pnpm install novamente para validar se as mudanças podem ser aplicadas sem o campo overrides.

Solução de problemas

Os passos acima são o caso ideal. As coisas nem sempre acontecem como o esperado. Aqui estão algumas dicas para a solução de problemas:

A versão é revertida após remover o campo "overrides"

Isso pode acontecer quando o pacote dependente tem uma versão fixa ou um intervalo que não inclui a versão desejada. Verifique o arquivo package.json do pacote dependente, neste caso, axios, para ver se isso se aplica.

Se for o caso, você precisará manter o campo overrides no arquivo package.json até que o pacote dependente atualize as definições de versão.

Existem múltiplas resoluções para a dependência transitiva

À medida que o projeto cresce, o arquivo pnpm-lock.yaml pode inflar com várias resoluções para o mesmo pacote. Por exemplo, pode haver duas versões principais do mesmo pacote foo:

O relatório de vulnerabilidade mostra que [email protected] tem um problema de segurança que é corrigido na 1.0.1, e [email protected] não é afetado. Não podemos simplesmente adicionar um override ao foo:

  • Se adicionarmos um override "foo": "^1.0.1", o [email protected] será rebaixado para 1.0.1. Isso pode quebrar o projeto, pois o [email protected] pode ter alguns novos recursos que são usados nos pacotes dependentes.
  • Se adicionarmos um override "foo": "^2.0.0", o [email protected] será atualizado para 2.0.0. Isso pode quebrar o projeto, pois o [email protected] pode ter algumas mudanças que causam quebra de compatibilidade.

Assumindo que foo segue a Versionamento Semântico, podemos adicionar um override assim:

Isso apenas atualizará o [email protected] para 1.0.1 e manterá o [email protected] inalterado.

Conclusão

Até que o PNPM suporte a atualização direta de dependências transitivas, o campo overrides é uma boa solução alternativa para corrigir vulnerabilidades de segurança sem quebrar nada. Espero que este artigo ajude você a lidar com esses casos de maneira mais eficiente. No Logto, usamos esse método para manter nossas dependências atualizadas e seguras.