In this article
Decifrando CVEs: um guia prático para avaliar e mitigar riscos de segurança
Resumo
Vamos explorar o universo das Vulnerabilidades e Exposições Comuns (CVEs) com exemplos passo a passo de como avaliar se uma CVE afeta seu projeto e estratégias práticas para mitigá-la com eficácia. Este guia vai ajudar você a enfrentar as vulnerabilidades de segurança de frente. Não deixe os alertas de CVE passarem despercebidos — aprenda a lidar com eles com confiança e eficiência.
Conteúdo
Como desenvolvedores, estamos sempre equilibrando vários projetos e priorizando correções de bugs e melhorias de funcionalidades. Ainda assim, em meio a esse ritmo intenso, muitas vezes nos deparamos com a realidade preocupante de que nossos projetos podem estar vulneráveis a Vulnerabilidades e Exposições Comuns (CVEs). A cada dia, o número de CVEs divulgadas continua aumentando, o que torna a segurança dos nossos projetos um desafio e tanto. Mas não se preocupe: vou compartilhar estratégias práticas para enfrentar esse problema. Neste artigo, vou apresentar algumas abordagens para integrar a análise de CVEs ao seu fluxo de desenvolvimento sem complicações, ajudando você a proteger seus projetos com confiança
Sem uma estratégia clara para mitigar as CVEs, é muito fácil se sentir sobrecarregado com o número de CVEs descobertas todos os dias, especialmente no ecossistema Node.js, onde é muito comum que nossas aplicações tenham muitas dependências. Ulises Gascón. Node.js para iniciantes (Capítulo 15. Protegendo aplicações Web)
Como analisar uma CVE?
Vamos usar a CVE-2020-8203 como exemplo. Essa vulnerabilidade de poluição de protótipo afeta a popular biblioteca Lodash.
Dependendo das ferramentas usadas para receber alertas sobre vulnerabilidades no nosso projeto, podemos encontrar relatórios diferentes que apresentam informações mais ou menos semelhantes:
Como você pode ver, as duas imagens apresentam informações semelhantes (principalmente metadados) sobre a vulnerabilidade. No entanto, cada descrição traz informações diferentes que podem enriquecer nossa análise.

Analise a gravidade
Primeiro, podemos usar a gravidade para ajudar a priorizar o trabalho. Ela é baseada em uma escala de um a dez, calculada pelo Sistema Comum de Pontuação de Vulnerabilidades (CVSS). Essa pontuação também é detalhada e pode nos dar bastante contexto. A ideia é priorizar a aplicação de patches de acordo com a criticidade, caso tenhamos várias vulnerabilidades para analisar.
Os resultados podem variar dependendo da fonte das informações. Na imagem abaixo, vemos que a Snyk atribui a pontuação 8,2, enquanto a Red Hat e o NVD atribuem 7,4.

Não importa qual sistema de pontuação você usa, desde que seja sempre o mesmo. Em geral, vale a pena analisar as CVEs de gravidade crítica ou alta, enquanto as de menor gravidade podem esperar um pouco mais.
É importante entender que, assim que uma CVE é divulgada publicamente, qualquer pessoa no mundo pode ficar sabendo dela. Por isso, agentes mal-intencionados podem facilmente adicionar CVEs críticas ao seu arsenal e começar a usá-las para explorar sistemas, se encontrarem uma forma de fazer isso.
Se você não conhece a velocidade com que agentes mal-intencionados agem, confira este relatório de honeypot.
Busque mais informações
O próximo passo é reunir o máximo possível de informações sobre a vulnerabilidade e sua possível exploração. Às vezes, você consegue muitas informações consultando os links na seção de referências da página oficial do relatório da CVE.

Neste caso, podemos até ler o relatório original no HackerOne e a discussão entre quem reportou a vulnerabilidade e os responsáveis pela manutenção. Isso pode nos trazer muitas informações. Neste exemplo, encontramos informações úteis nos relatórios da Snyk e do GitHub.
Delimite a superfície de ataque
Com base na etapa anterior, devemos saber quais versões da biblioteca são afetadas (>=4.1.0 <4.17.20) e quais métodos são abrangidos por essa vulnerabilidade (pick, set, setWith, update, updateWith e zipObjectDeep) — lembrando que estamos lidando com uma vulnerabilidade de poluição de protótipo.
Podemos fazer uma verificação rápida no repositório para avaliar se estamos expostos. Se não estivermos usando esses métodos com essas versões específicas, podemos confirmar que nosso código não é afetado e que, no nosso caso, trata-se de um falso positivo.
Essa avaliação pode ser mais complexa do que parece. No ecossistema JavaScript, é muito comum que ferramentas de desenvolvimento tenham devDependencies que não afetam de fato o ambiente de produção — por exemplo, linters, frameworks de teste, certos utilitários etc. Isso depende muito das características do projeto. Podemos usar o PM2 localmente para simular um ambiente de produção, mas usar contêineres e Kubernetes para implantar nossos projetos em produção. Isso reduz bastante os vetores de ataque para CVEs relacionadas ao PM2, pois, na maioria dos casos, usamos a ferramenta em um “ambiente seguro” que controlamos por completo. Mas lembre-se: mesmo que o pacote não seja usado em produção, ele pode causar danos se for comprometido no ambiente de desenvolvimento. Por exemplo, o eslint foi comprometido em 2018.
Se não tivermos um argumento claro para descartar o impacto dessa vulnerabilidade no nosso projeto, é mais seguro considerar que estamos sujeitos a ela e que talvez precisemos adotar uma medida de mitigação adequada.
Além das informações na descrição, uma boa maneira de entender melhor a técnica de ataque é consultar as Enumerações de Fraquezas Comuns (CWEs) mencionadas na CVE.

Neste caso, a CWE mencionada foi a CWE-1321: Modificação inadequadamente controlada de atributos do protótipo de objeto (“poluição de protótipo”). Isso nos ajuda a encontrar CVEs semelhantes e a entender melhor como a vulnerabilidade pode ser explorada.
Em poucas palavras, a CWE é uma lista de possíveis fraquezas, enquanto a CVE é uma lista de vulnerabilidades descobertas no mundo real. Ulises Gascón. Node.js para iniciantes
Há uma prova de conceito explorável?
Nem todas as CVEs incluem uma prova de conceito (POC) da vulnerabilidade reportada que possa ser explorada facilmente, mas neste caso temos uma bem clara:
const _ = require('lodash');
_.zipObjectDeep(['__proto__.z'],[123]);
console.log(z); // 123
Além de nos ajudar a entender melhor o problema, isso pode nos ajudar a testar nosso código e confirmar a vulnerabilidade. Vamos supor que temos o seguinte código na nossa aplicação:
const _ = require('lodash');
const normalizeData = (users, ages) => {
return _.zipObjectDeep(users,ages);
}
module.exports = { normalizeData }
É fácil concluir que o código é vulnerável a um ataque de poluição de protótipo, mas também podemos criar um teste para garantir que temos mecanismos para evitar que essas vulnerabilidades ocorram no futuro. Às vezes, as bibliotecas introduzem regressões que contêm vulnerabilidades. Podemos evitar isso adicionando um teste simples, como este:
const { normalizeData } = require('../utils');
describe('normalizeData behaviour', () => {
it('should return the data structured properly', () => {
const users = ['John', 'Doe'];
const ages = [30, 40];
const result = normalizeData(users, ages);
expect(result).toEqual({ John: 30, Doe: 40 });
});
it('should not be affected by a prototype pollution (CVE-2020-8203)', () => {
normalizeData(['__proto__.z'], [123]);
expect(global.z).toBe(undefined);
});
});
Obviamente, esse teste vai falhar, pois no momento estamos vulneráveis a essa poluição de protótipo e não fizemos nenhuma alteração no projeto para mitigá-la.

figura: usando Node.js@21 e lodash@4.17.0
Agora, vamos ver como podemos mitigar essa vulnerabilidade.
Estratégias para mitigar uma CVE
Há várias estratégias para mitigar uma CVE. Vamos explorar algumas delas, da que exige menos esforço à que exige mais.
Atualize ou volte para outra versão
A forma mais recomendada de mitigar uma CVE é atualizar a versão da biblioteca afetada. Neste caso, podemos atualizar para lodash@4.17.20 ou superior. Geralmente, esse é o melhor método, porque os responsáveis pela manutenção da biblioteca disponibilizam uma correção para a vulnerabilidade, que também foi testada com quem a reportou. Assim, podemos ter certeza de que o patch funciona.
Se aplicarmos este patch (npm i lodash@4.17.20), podemos executar novamente o teste que criamos e confirmar que a vulnerabilidade foi mitigada.

Figura: usando Node.js@21 e lodash@4.17.21
Embora pareça simples, essa tarefa pode se tornar bem complexa. Talvez seja necessário atualizar ou rebaixar outras dependências incompatíveis com a nova versão da biblioteca, ou a versão mais recente pode conter outras alterações incompatíveis com nosso código.
Em outros casos, a CVE é divulgada antes do lançamento do patch. Então, precisamos recorrer a outras estratégias para mitigar a vulnerabilidade enquanto aguardamos a correção definitiva.
Migre para outra biblioteca
Se a biblioteca não tiver mais manutenção ou se os responsáveis não disponibilizarem um patch para a vulnerabilidade, talvez seja necessário migrar para outra biblioteca com funcionalidades iguais ou semelhantes. Embora exija bastante esforço, pode ser um bom investimento se a nova biblioteca for mais segura e tiver manutenção ativa.
Assim, podemos reduzir o número de CVEs que teremos de analisar no futuro e gerenciar as atualizações com mais facilidade.
Aplicação manual de patches (DIY)
Se não pudermos atualizar a biblioteca nem migrar para outra, talvez seja necessário aplicar o patch por conta própria. Essa também é uma estratégia válida quando a CVE é divulgada antes do lançamento do patch e precisamos mitigar a vulnerabilidade o quanto antes, enquanto aguardamos a correção oficial.
Qualquer patch manual exige um bom entendimento da biblioteca e da vulnerabilidade. Podemos usar a POC incluída no relatório da CVE para criar nosso próprio patch e o teste que desenvolvemos para confirmar que ele funciona. Vamos ver como criar um patch para essa vulnerabilidade:
const _ = require('lodash');
const normalizeData = (users, ages) => {
const safeUsers = users.filter(user => !/__proto__|prototype|constructor/.test(user));
return _.zipObjectDeep(safeUsers, ages);
}
module.exports = { normalizeData }
Este é um patch simples que mostra como mitigar a vulnerabilidade, mas, para garantir maior conformidade, consulte o patch oficial, pois nosso caso de teste foi bastante básico. Agora, podemos executar o teste novamente e confirmar que a vulnerabilidade foi mitigada.

Figura: usando Node.js@21, lodash@4.17.0 e o patch
Estratégias para documentar decisões sobre CVEs
Ao trabalhar em equipe, é importante documentar as decisões tomadas sobre as CVEs. Isso ajuda a acompanhar as vulnerabilidades que mitigamos e as que ainda estão pendentes. Também ajuda a priorizar o trabalho e garante que nenhuma vulnerabilidade passe despercebida.
Podemos usar uma tabela simples para documentar as CVEs que estamos analisando, a gravidade, o status, a estratégia de mitigação e a data em que a vulnerabilidade foi mitigada. Assim, fica mais fácil acompanhar as vulnerabilidades já mitigadas e as que ainda estão pendentes.
CVE | Gravidade | Status | Estratégia de mitigação | Data |
CVE-2020-8203 | 8.2 | Mitigada | Atualizar para lodash@4.17.21 | 2024-04-15 |
Essa tabela pode ser atualizada sempre que analisarmos uma CVE e compartilhada com a equipe para que todos saibam quais vulnerabilidades estamos enfrentando e quais já foram mitigadas.
Melhor ainda: você pode incluir essa tabela na documentação do projeto para que ela faça parte do processo de distribuição do código.
Se você usa uma ferramenta para analisar CVEs, pode ser difícil indicar o status das CVEs identificadas como falsos positivos ou corrigidas com um patch manual. Por exemplo, se você usa a Snyk, pode marcar a CVE como ignorada.
No nosso caso, se você aplicou o patch manual, pode marcar a CVE como ignorada no relatório da Snyk desta forma: snyk ignore --id=SNYK-JS-LODASH-567746 --reason="manual patch in place with tests".
Isso vai gerar o seguinte conteúdo no arquivo .snyk:
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
version: v1.25.0
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
ignore:
SNYK-JS-LODASH-567746:
- '*':
reason: manual patch in place with tests
expires: 2024-05-15T17:27:20.339Z
created: 2024-04-15T17:27:20.340Z
patch: {}
Em geral, o processo exige algum trabalho manual, e é altamente recomendável trabalhar em equipe para reduzir ao máximo vieses e erros humanos.
Checklist
Em resumo, estes são os passos que precisamos seguir para analisar uma CVE:
Analise a gravidade da CVE
Busque mais informações sobre o vetor de ataque
Delimite a superfície de ataque
Verifique se há uma POC explorável
Avalie o impacto no seu projeto
Mitigue a vulnerabilidade, se necessário
Documente as decisões tomadas sobre as CVEs
Compartilhe as conclusões com sua equipe
Recursos adicionais
Se quiser explorar outros temas relacionados à segurança no Node.js, confira meu livro Node.js para iniciantes, no qual abordo vários assuntos sobre segurança no Node.js.
Proteja seu código com inteligência de ponta
Conheça toda a gama de recursos de análise estática (SAST) do Snyk Code em apenas 30 minutos.