---
title: "govulncheck em Go: Vulnerabilidades que Importam"
url: "https://golang.com.br/blog/govulncheck-go-vulnerabilidades-dependencias/"
markdown_url: "https://golang.com.br/blog/govulncheck-go-vulnerabilidades-dependencias.MD"
description: "Aprenda a usar govulncheck em projetos Go: diferença para scanner genérico, CI, triagem de CVEs, upgrades seguros e rotina de produção."
date: "2026-06-05"
author: "Golang Brasil"
---

# govulncheck em Go: Vulnerabilidades que Importam

Aprenda a usar govulncheck em projetos Go: diferença para scanner genérico, CI, triagem de CVEs, upgrades seguros e rotina de produção.


`govulncheck` é a ferramenta oficial do ecossistema Go para responder uma pergunta mais útil do que “existe algum CVE em alguma dependência?”: o seu código realmente chama o caminho vulnerável? Em projetos Go com APIs, workers, CLIs e serviços internos, essa diferença muda a rotina de segurança. Um scanner genérico pode apontar dezenas de alertas em módulos transitivos. O govulncheck cruza seu código, suas dependências e a base de vulnerabilidades do Go para priorizar o que tem caminho de chamada alcançável.

Isso não significa ignorar dependência velha. Significa separar urgência real de ruído. Em um time brasileiro pequeno, onde a mesma pessoa escreve feature, revisa PR, opera deploy e responde incidente, o custo de triagem importa. Uma rotina boa combina `go mod tidy`, atualização planejada, testes, CI e govulncheck como portão de segurança proporcional ao risco.

Este guia mostra como usar govulncheck em projetos Go, como interpretar o resultado, como colocar no CI sem travar o time por falso positivo e como decidir upgrade, mitigação ou aceite temporário. Ele complementa [Go Modules na prática](/aprenda/go-modules-na-pratica/), [TDD e CI/CD em Go](/tutoriais/go-tdd-ci-cd/), [segurança em Go](/tutoriais/go-security/) e [GoReleaser com checksums e SBOM](/blog/goreleaser-go-binarios-checksums-sbom/).

## Por que scanner genérico não basta

Muitos scanners olham para `go.mod`, `go.sum` ou para o SBOM e comparam versões contra bases de CVEs. Isso é útil, mas incompleto. Se uma dependência transitiva tem uma vulnerabilidade em um pacote que seu binário nunca importa, o risco é diferente de uma falha em `crypto`, `net/http`, parser de JWT, template HTML ou client exposto a dados de usuário.

Go tem uma vantagem técnica: o ecossistema consegue analisar pacotes, símbolos e chamadas com bastante precisão. O govulncheck usa a base pública de vulnerabilidades do Go e tenta descobrir se o programa chama funções afetadas. O resultado fica mais perto da pergunta operacional: “preciso agir antes do próximo deploy?”

Exemplo de diferença:

- Um módulo vulnerável existe no grafo, mas nenhum pacote afetado é importado.
- Um pacote afetado é importado, mas a função vulnerável não é chamada.
- A função vulnerável está no caminho de chamada do seu código.
- A vulnerabilidade está na biblioteca padrão usada pela versão de Go do build.

Os quatro cenários pedem respostas diferentes. Tratar todos como emergência cria fadiga. Tratar todos como detalhe cria risco acumulado.

## Instalação e primeiro uso

Instale a ferramenta oficial:

```bash
go install golang.org/x/vuln/cmd/govulncheck@latest
```

Depois rode na raiz do módulo:

```bash
govulncheck ./...
```

Em um monorepo com vários módulos, rode por módulo ou automatize a descoberta de diretórios com `go.mod`. O importante é executar no mesmo contexto em que o projeto compila: variáveis de build, tags e versão de Go podem mudar o conjunto de pacotes analisados.

Para ver mais detalhes:

```bash
govulncheck -v ./...
```

Em projetos com tags específicas:

```bash
govulncheck -tags "prod,postgres" ./...
```

Se seu serviço usa código condicionado por `//go:build`, não esqueça esse ponto. Um scanner rodando sem as tags de produção pode deixar de enxergar justamente o caminho usado no deploy.

## Como ler o resultado

O resultado do govulncheck normalmente traz três blocos importantes: o identificador da vulnerabilidade, os módulos/versões afetados e a cadeia de chamada quando há código alcançável.

A parte mais importante é a call stack. Se ela aparece, existe um caminho do seu código até uma função vulnerável. Algo como:

```text
Vulnerability #1: GO-2026-1234
  Example issue in module example.org/lib
  Found in: example.org/lib@v1.2.3
  Fixed in: example.org/lib@v1.2.4
  Example traces found:
    main.handleUpload calls parser.Parse
    parser.Parse calls example.org/lib.Decode
```

Nesse cenário, a triagem é objetiva:

1. Existe versão corrigida?
2. O upgrade quebra API?
3. Há teste cobrindo o caminho afetado?
4. O endpoint recebe entrada externa?
5. Existe mitigação temporária, como bloquear formato, limitar tamanho ou desativar feature?

Se o relatório aponta módulo vulnerável sem caminho alcançável, ainda vale planejar atualização, mas a urgência cai. Em produto com deploy frequente, o melhor caminho costuma ser atualizar no próximo ciclo normal e manter o scanner verde.

## Biblioteca padrão também entra na conta

Nem toda vulnerabilidade vem de dependência externa. O próprio toolchain Go e a biblioteca padrão recebem correções de segurança. Se uma falha afeta `net/http`, `crypto/x509`, `archive/zip`, `html/template` ou outro pacote padrão, a correção pode exigir atualizar a versão de Go usada no build.

Por isso, o pipeline precisa deixar claro qual Go compila o binário. Não basta rodar govulncheck localmente com Go novo se o CI ainda usa uma imagem antiga. Verifique:

```bash
go version
go env GOVERSION
```

Em Docker, prefira imagem de build com versão explícita:

```dockerfile
FROM golang:1.25-bookworm AS build
```

E evite deixar `latest` como contrato de produção. `latest` muda sem review. Use atualização intencional, changelog e testes.

Esse cuidado conversa com [GoReleaser](/blog/goreleaser-go-binarios-checksums-sbom/): release confiável precisa dizer qual commit, qual versão de Go, quais dependências e qual artefato foram publicados.

## CI sem virar bloqueio burro

O govulncheck deve rodar no CI, mas a política precisa ser honesta. Em projetos novos ou pequenos, um job que falha quando há vulnerabilidade alcançável é razoável. Em bases grandes, talvez seja necessário começar em modo informativo por uma semana, limpar o backlog e só então tornar obrigatório.

Um workflow simples de GitHub Actions ficaria assim:

```yaml
name: security

on:
  pull_request:
  push:
    branches: [main]

jobs:
  govulncheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version-file: go.mod
      - run: go test ./...
      - run: go install golang.org/x/vuln/cmd/govulncheck@latest
      - run: govulncheck ./...
```

Se você já usa [TDD e CI/CD em Go](/tutoriais/go-tdd-ci-cd/), coloque esse job perto de testes e lint. A ordem prática costuma ser:

1. `gofmt` ou `gofmt -w` verificado.
2. `go test ./...`.
3. `go vet ./...` ou lint.
4. `govulncheck ./...`.
5. Build ou empacotamento.

Rodar teste antes ajuda a distinguir projeto quebrado de vulnerabilidade. Se o módulo nem compila, o relatório de segurança perde valor.

## Política de triagem para PRs

Sem política, cada alerta vira discussão repetida. Uma política simples pode caber no README:

| Situação | Ação padrão |
|---|---|
| Vulnerabilidade alcançável com fix disponível | Atualizar dependência ou Go antes do merge |
| Vulnerabilidade alcançável sem fix | Mitigar, documentar risco e abrir issue datada |
| Módulo vulnerável sem caminho alcançável | Atualizar no ciclo normal, salvo pacote crítico |
| Scanner falhou por indisponibilidade externa | Reexecutar; não ignorar sem evidência |
| Dependência nova traz alerta | Bloquear PR até justificar ou trocar dependência |

O ponto é tirar subjetividade do calor do deploy. Em sistemas que processam pagamento, autenticação, documento, saúde, dado pessoal ou upload de usuário, suba o nível. Em ferramentas internas sem entrada externa, ainda trate segurança com respeito, mas priorize proporcionalmente.

## Atualização segura de dependências

Ao corrigir um alerta, não rode `go get -u ./...` sem pensar. Isso atualiza mais do que você pretendia e pode criar mudança grande demais. Prefira upgrade direcionado:

```bash
go get example.org/lib@v1.2.4
go mod tidy
go test ./...
govulncheck ./...
```

Depois revise o diff de `go.mod` e `go.sum`. Se muitas dependências transitivas mudaram, entenda por quê. Em bibliotecas de segurança, HTTP, banco ou serialização, leia release notes quando houver.

Para atualizar a versão de Go do módulo:

```bash
go mod edit -go=1.25
go mod tidy
go test ./...
govulncheck ./...
```

Também atualize a imagem de CI, Dockerfile, `.tool-versions`, `mise.toml`, `goenv` ou qualquer arquivo que fixe versão. Metade das falhas de segurança em build vem de atualizar um lugar e esquecer outro.

## O que govulncheck não resolve

Govulncheck é excelente, mas não substitui engenharia de segurança. Ele não prova que sua API valida autorização corretamente, que seu segredo não vazou, que seu bucket está privado ou que seu SQL está protegido contra lógica de negócio ruim.

Ele também não cobre tudo que um scanner de container cobre. Um binário Go pode estar limpo, mas a imagem Docker pode trazer pacote do sistema vulnerável, shell desnecessário, certificado antigo ou usuário root. Para serviços em produção, combine:

- Govulncheck para código Go e dependências Go.
- Scanner de imagem para base Docker.
- SBOM para rastrear artefatos.
- Revisão de segredos e configuração.
- Testes de autorização e validação de entrada.
- Logs e métricas para detectar abuso.

Se você trabalha com múltiplas stacks, compare com a rotina de <a href="https://python.dev.br/blog/seguranca-dependencias-python-pip-audit/" target="_blank" rel="noopener noreferrer" onclick="umami.track('portfolio-site-click', { destination: 'python.dev.br' })">auditoria de dependências Python</a>. A linguagem muda, mas a disciplina é parecida: reduzir ruído, corrigir caminho explorável e manter o build reproduzível.

## Checklist para produção

Use este checklist em projetos Go que já rodam fora da sua máquina:

- [ ] `govulncheck ./...` roda localmente.
- [ ] O CI usa a mesma versão de Go esperada para produção.
- [ ] Tags de build relevantes são passadas ao scanner.
- [ ] Vulnerabilidade alcançável bloqueia merge ou deploy.
- [ ] Dependência nova passa por revisão mínima de manutenção e licença.
- [ ] Atualizações usam `go get pacote@versão`, não upgrade global sem motivo.
- [ ] `go.mod` e `go.sum` são revisados no PR.
- [ ] Imagem Docker não depende de `latest` sem controle.
- [ ] Release registra versão de Go, commit e artefatos.
- [ ] Existe dono claro para triagem de alertas de segurança.

Esse processo não precisa ser pesado. O erro é tratar segurança como auditoria anual. Em Go, a ferramenta é rápida o suficiente para virar hábito de PR.

## Conclusão

Govulncheck ajuda projetos Go a sair do teatro de segurança e chegar em uma triagem mais útil: quais vulnerabilidades estão realmente no caminho do meu código? Use a ferramenta para reduzir ruído, mas não para reduzir responsabilidade.

A rotina saudável é simples: dependências explícitas, versão de Go fixada, testes passando, govulncheck no CI, upgrades pequenos e release rastreável. Isso protege o usuário, reduz surpresa em produção e ainda melhora sua maturidade como pessoa desenvolvedora Go.

Se o seu projeto já tem `go test`, `go vet`, build reproduzível e govulncheck rodando, você está bem à frente de muita base que só descobre vulnerabilidade quando o alerta vira incidente.
