Fala Guerreiros e Guerreiras!
Hoje ao som da obra prima do Sólstafir - Svartir Sandar, navegando em águas gélidas da Islândia ao post-metal.
Uma aplicação pode ter uma boa arquitetura, testes automatizados, cobertura de código elevada e um pipeline de CI/CD funcionando perfeitamente. Ainda assim, pode carregar uma vulnerabilidade conhecida em uma biblioteca, no próprio framework ou em uma dependência indireta.
É nesse cenário que entram as CVEs.
Neste artigo, vamos entender o que significa uma CVE, como interpretar a gravidade de uma vulnerabilidade e como incorporar verificações de segurança a um projeto Ruby on Rails sem transformar a atualização de dependências em uma operação de risco.
1. O que é uma CVE?
CVE é a sigla para Common Vulnerabilities and Exposures. O programa CVE atribui identificadores padronizados a vulnerabilidades de segurança conhecidas publicamente, facilitando a comunicação entre desenvolvedores, pesquisadores, empresas e ferramentas de segurança.
Um identificador tem, normalmente, este formato:
CVE-2025-12345
Esse exemplo é apenas ilustrativo, não representa uma vulnerabilidade específica.
Uma CVE pode estar relacionada a diferentes tipos de problemas, como:
- execução de código não autorizada;
- exposição de informações sensíveis;
- falhas de autenticação ou autorização;
- ataques de negação de serviço;
- injeção de comandos ou consultas;
- leitura ou manipulação indevida de arquivos.
É importante entender uma diferença: a CVE é o identificador da vulnerabilidade, não uma medida completa do risco que ela representa para determinada aplicação.
Para pesquisar informações, podemos consultar o programa CVE e a National Vulnerability Database (NVD).
2. CVE e CVSS são a mesma coisa?
Não. Embora estejam relacionados, os conceitos são diferentes.
A CVE identifica uma vulnerabilidade. Já o CVSS (Common Vulnerability Scoring System) fornece uma pontuação e uma classificação de severidade, considerando características técnicas da falha.
De maneira geral, as classificações mais conhecidas são:
| Pontuação CVSS | Classificação |
|---|---|
| 0,0 | Nenhuma |
| 0,1 a 3,9 | Baixa |
| 4,0 a 6,9 | Média |
| 7,0 a 8,9 | Alta |
| 9,0 a 10,0 | Crítica |
Essas faixas correspondem ao CVSS v3.x; outras versões podem apresentar diferenças de classificação.
Mas atenção: uma vulnerabilidade classificada como crítica não significa automaticamente que qualquer aplicação que utilize aquela biblioteca esteja explorável. Da mesma forma, uma falha de severidade média pode representar um risco importante dependendo dos dados tratados, da exposição da aplicação e das permissões envolvidas.
A análise precisa considerar pelo menos quatro aspectos:
- Severidade: qual é o impacto técnico potencial?
- Exposição: o componente vulnerável está acessível a usuários ou sistemas externos?
- Aplicabilidade: a aplicação utiliza a funcionalidade afetada?
- Mitigação: existe uma correção disponível ou uma medida temporária eficaz?
A pontuação ajuda a priorizar. Ela não substitui a análise de risco.
Referência: NVD — informações sobre CVEs e CVSS.
3. Por que isso importa em projetos Ruby on Rails?
Uma aplicação Rails não é composta apenas pelo código escrito pela equipe.
Ela utiliza o Ruby, o framework Rails, gems diretamente declaradas no Gemfile e diversas dependências indiretas. Também depende do sistema operacional, de imagens de contêiner, do servidor web, do banco de dados e de outros componentes da infraestrutura.
Considere um projeto com esta estrutura simplificada:
- Ruby;
- Rails;
- Devise para autenticação;
- Sidekiq para processamento em segundo plano;
- Redis para filas e armazenamento;
- PostgreSQL para persistência;
- gems adicionais para arquivos, relatórios e integrações.
Uma vulnerabilidade pode estar em qualquer componente afetado, e nem sempre a dependência problemática foi adicionada diretamente pela equipe.
Por exemplo, uma gem pode depender de outra biblioteca que apresenta uma falha conhecida. Mesmo que o projeto não tenha declarado essa segunda biblioteca diretamente, ela pode aparecer no Gemfile.lock.
É por isso que revisar somente o código da aplicação não é suficiente.
4. Primeiro passo: auditar as gems com Bundler Audit
Uma das ferramentas mais úteis nesse contexto é o bundler-audit, mantido pelo projeto RubySec.
Ele verifica o arquivo Gemfile.lock em busca de dependências com vulnerabilidades registradas na base de avisos de segurança utilizada pela ferramenta. Também verifica fontes inseguras de gems.
Repositório oficial: rubysec/bundler-audit.
Instalação
Podemos adicionar a ferramenta ao grupo de desenvolvimento do projeto:
group :development do
gem "bundler-audit"
end
Depois, instalamos a dependência:
bundle install
Também é possível instalar a ferramenta separadamente, conforme a política de ferramentas adotada pela equipe.
Executando a auditoria
Para atualizar a base de avisos e verificar as dependências:
bundle exec bundle-audit check --update
O comando utiliza o executável bundle-audit e verifica as versões registradas no Gemfile.lock.
Quando uma vulnerabilidade é encontrada, a saída pode apresentar informações como:
- nome da gem;
- versão instalada;
- identificador da vulnerabilidade;
- descrição do problema;
- severidade, quando disponível;
- versão ou versões recomendadas para correção;
- referência para consultar o aviso completo.
Um resultado encontrado não deve ser ignorado automaticamente. É necessário consultar o aviso, confirmar quais versões são afetadas e entender o impacto no projeto.
Para gerar um relatório em JSON:
bundle exec bundle-audit check \
--update \
--format json \
--output bundle-audit.json
A disponibilidade e o comportamento de opções podem variar conforme a versão instalada. Consulte a documentação da versão utilizada no projeto.
Um detalhe importante
Executar uma auditoria apenas uma vez não resolve o problema permanentemente.
Novos avisos são publicados, dependências recebem atualizações e a situação do projeto pode mudar. Por isso, essa verificação deve fazer parte da rotina de manutenção e do pipeline de integração contínua.
5. Encontrou uma vulnerabilidade. E agora?
Imagine que a auditoria identificou uma versão vulnerável de uma gem.
A primeira reação não deve ser atualizar todas as dependências indiscriminadamente.
Uma atualização ampla pode alterar APIs, introduzir incompatibilidades e provocar falhas em funcionalidades que estavam funcionando corretamente.
Um procedimento mais cuidadoso seria:
Etapa 1 — Identificar a origem da dependência
Consulte a árvore de dependências:
bundle info nome-da-gem
Para entender quais dependências introduzem determinada gem, utilize:
bundle why nome-da-gem
Esse segundo comando depende da versão do Bundler instalada. Caso não esteja disponível, consulte a documentação correspondente ou examine a árvore de dependências por outro meio.
Etapa 2 — Consultar o aviso de segurança
Leia a referência indicada pela ferramenta e confirme:
- quais versões são afetadas;
- qual é a versão corrigida;
- quais condições tornam a falha relevante;
- se existem limitações ou mitigações documentadas.
Não confie somente no título de um alerta ou em uma pontuação.
Etapa 3 — Atualizar a dependência necessária
Quando a correção estiver disponível, uma opção é atualizar a gem de forma conservadora:
bundle update --conservative nome-da-gem
O comportamento exato depende das restrições definidas no Gemfile e das relações entre dependências. Em alguns casos, será necessário atualizar outras gems ou ajustar as restrições de versão.
Revise o Gemfile.lock para entender quais componentes foram alterados.
Etapa 4 — Executar os testes
Após a atualização:
bundle exec rspec
Se o projeto tiver verificações adicionais:
bundle exec rubocop
bundle exec brakeman
Esses comandos verificam aspectos diferentes: testes automatizados, padrões de código e possíveis problemas de segurança identificáveis por análise estática.
Testes passando não provam que a vulnerabilidade foi corrigida. É preciso confirmar a versão instalada e executar novamente a auditoria de dependências.
A documentação oficial do Rails também recomenda atualizações cuidadosas de dependências: Securing Rails Applications.
6. CVE não é a única verificação de segurança
Uma auditoria de dependências é importante, mas tem um escopo específico. Ela não substitui a análise do código da aplicação.
Em um projeto Rails, podemos combinar ferramentas com objetivos complementares:
| Ferramenta | Objetivo principal |
|---|---|
| Bundler Audit | Identificar gems afetadas por avisos conhecidos |
| Brakeman | Detectar possíveis problemas de segurança no código Rails |
| RSpec | Verificar comportamentos esperados por meio de testes |
| RuboCop | Verificar estilo, convenções e regras de análise estática |
| Ferramentas de auditoria de contêineres | Identificar componentes vulneráveis em imagens e pacotes do sistema |
Cada ferramenta tem limitações. Nenhuma delas, isoladamente, garante que a aplicação esteja segura.
Também é importante considerar a versão do Ruby, o sistema operacional, a imagem de contêiner e os serviços externos. Uma auditoria de gems não examina automaticamente toda a infraestrutura.
7. Automatizando a verificação no CI/CD
Uma prática recomendada é executar a auditoria de dependências automaticamente em cada pipeline relevante.
Um exemplo de etapa para um ambiente de CI que já tenha Ruby e Bundler configurados seria:
bundle install
bundle exec bundle-audit check --update
bundle exec rspec
O objetivo é identificar problemas antes que uma alteração seja integrada ou implantada.
Em um ambiente real, convém separar as etapas, armazenar os relatórios como artefatos e definir uma política para falhas de segurança.
Por exemplo:
- bloquear a integração quando uma vulnerabilidade crítica ou de alto risco for confirmada, conforme a política do projeto;
- abrir uma tarefa de correção para alertas que precisem de investigação;
- registrar exceções com justificativa, responsável e prazo de revisão;
- manter uma rotina de atualização da base de avisos;
- repetir a auditoria antes da implantação, quando apropriado.
Uma exceção não deve virar uma autorização permanente para ignorar alertas.
Se a equipe decidir aceitar temporariamente um risco, essa decisão precisa ser documentada, justificada e revisada. Quando a ferramenta permite ignorar um aviso específico, prefira uma exceção restrita e rastreável em vez de desativar toda a verificação.
8. O problema de ignorar alertas sem investigar
Imagine uma aplicação de gestão comercial que utiliza Rails para processar pedidos, registrar pagamentos e controlar estoque.
A auditoria encontra uma dependência vulnerável. A equipe, pressionada pelo prazo, adiciona uma exceção para que o pipeline continue passando.
O sistema segue funcionando, os testes continuam verdes e a implantação ocorre normalmente.
Mas o alerta não desapareceu por ter sido ignorado. A vulnerabilidade continua exigindo análise e, dependendo das condições de exploração, pode representar um risco para a aplicação e seus dados.
O mesmo problema acontece quando uma equipe atualiza uma biblioteca sem consultar a documentação e sem validar a compatibilidade.
Segurança exige equilíbrio: corrigir vulnerabilidades com prioridade, evitar mudanças desnecessárias e comprovar que a correção funcionou.
9. Um checklist para projetos Rails
Antes de considerar a auditoria concluída, verifique:
- [ ] O
Gemfile.lockestá versionado e corresponde às dependências utilizadas? - [ ] A base de avisos foi atualizada durante a auditoria?
- [ ] Os alertas encontrados foram analisados e priorizados?
- [ ] As dependências vulneráveis foram atualizadas para versões corrigidas compatíveis?
- [ ] O arquivo
Gemfile.lockfoi revisado? - [ ] Os testes automatizados passaram após as alterações?
- [ ] A auditoria foi executada novamente?
- [ ] As exceções foram justificadas e possuem prazo de revisão?
- [ ] A versão do Ruby, o sistema operacional e as imagens de contêiner também são verificados?
- [ ] O processo será repetido automaticamente no CI/CD?
Conclusão: segurança é um processo contínuo
CVE não é apenas uma sigla que aparece em relatórios de segurança. É uma referência para investigar vulnerabilidades conhecidas e tomar decisões técnicas fundamentadas.
No Ruby on Rails, ferramentas como Bundler Audit facilitam a identificação de gems vulneráveis. Entretanto, identificar uma falha é somente o começo: precisamos compreender o impacto, atualizar com cuidado, executar testes e confirmar que a correção foi aplicada.
Uma boa arquitetura, testes automatizados, análise estática e dependências atualizadas se complementam. Nenhum desses elementos substitui os demais.
E fica uma reflexão: se o pipeline está verde, mas ninguém verifica as vulnerabilidades das dependências, estamos medindo a qualidade do software ou apenas confirmando que ele continua funcionando?
Em desenvolvimento de software, funcionar é necessário. Manter o sistema seguro também faz parte da responsabilidade técnica.
Referências
- CVE Program — identificadores de vulnerabilidades
- NVD — National Vulnerability Database
- Bundler Audit — repositório e documentação
- Ruby on Rails Guides — Security
- Ruby on Rails — política de segurança