
Quando falamos de segurança em software, a maioria das empresas pensa em firewall, WAF, ou alguma ferramenta de varredura de vulnerabilidades rodando uma vez por mês. Mas a realidade é dura: a maioria das brechas exploradas em produção nasce dentro do código, não em ataques externos mirabolantes.
Segurança não pode ser uma camada colada no final do projeto. Ela precisa estar integrada ao DNA do desenvolvimento – o que o mercado chama de DevSecOps. E quando falamos de linguagens de alta performance como Go, essa integração tem características específicas.
Neste post, vamos mostrar como a Jacobus Software constrói software seguro desde a primeira linha de código, usando Go como ferramenta principal – sem sacrificar produtividade nem desempenho.
O mito de que “Go é seguro por padrão”
Go tem uma reputação merecida de segurança em relação a linguagens como C/C++. O garbage collector, o bounds checking em slices e a ausência de aritmética de ponteiros eliminam classes inteiras de vulnerabilidades (como buffer overflows).
Mas isso não torna o código Go automaticamente seguro.
As vulnerabilidades mais comuns no ecossistema Go hoje são outras:
- Injeção de SQL (mesmo com
database/sql, se você concatena strings). - Exposição de dados sensíveis em logs ou respostas de erro.
- Dependências maliciosas ou desatualizadas (o velho
go getpode trazer surpresas). - Race conditions em programas concorrentes (apesar do detector nativo, não pega tudo).
- Configurações inseguras em servidores HTTP (como
Debugativado em produção).
A segurança em Go exige disciplina, ferramentas e processo. Vamos ao que funciona.
1. Safer by default: as práticas mínimas no código
Trate todos os inputs como hostis
// ❌ Nunca faça isso
query := fmt.Sprintf("SELECT * FROM users WHERE id = %s", userInput)
rows, err := db.Query(query)
// ✅ Use prepared statements ou parametrização
rows, err := db.Query("SELECT * FROM users WHERE id = $1", userInput)
Evite vazar informações em erros
// ❌ Retorna detalhes internos
http.Error(w, "erro ao conectar ao banco: "+err.Error(), 500)
// ✅ Mensagem genérica, log detalhado no servidor
log.Printf("erro interno: %v", err)
http.Error(w, "erro interno do servidor", 500)
Timeouts em todas as operações externas
ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
defer cancel()
// Use ctx em chamadas HTTP, banco, etc.
Essas três práticas, aplicadas consistentemente, eliminam mais de 60% das vulnerabilidades comuns em APIs Go.
2. Ferramentas que não deixam passar nada
O ecossistema Go oferece ferramentas maduras de análise estática e dinâmica que devem fazer parte do CI/CD:
| Ferramenta | O que detecta | Como integrar |
|---|---|---|
go vet | Construções suspeitas (ex: formatos em Printf) | go vet ./... |
staticcheck | Bugs, performance, estilo | staticcheck ./... |
gosec | Vulnerabilidades específicas de segurança Go | gosec ./... |
govulncheck (oficial Go) | Vulnerabilidades conhecidas em dependências | govulncheck ./... |
go test -race | Race conditions | Sempre nos testes |
Na Jacobus, nenhum código chega ao main sem passar por essa bateria. É tão natural quanto go fmt.
3. Dependências: o calcanhar de Aquiles moderno
Um go.mod com 50 dependências indiretas é comum. Cada uma é um potencial vetor de ataque.
Nossa política:
- Use
go mod vendore commite ovendor/– você controla exatamente o que roda. - Execute
govulncheckdiariamente (via GitHub Actions ou similar). - Prefira dependências oficiais ou com alta adoção e manutenção ativa.
- Desconfie de libs que fazem requisições de rede sem necessidade.
Caso real: uma vulnerabilidade crítica em 2025 no pacote net/textproto (afetou muitos parsers) foi detectada pelo govulncheck em minutos em nossos projetos, e a correção foi aplicada antes de qualquer cliente ser impactado.
4. Segurança em produção com Go
Um binário Go estático é inerentemente mais seguro que uma aplicação Python ou Node.js que carrega dezenas de arquivos e dependências em runtime. Mas ainda há pontos de atenção:
- Use
GIN_MODE=releaseou equivalente – frameworks web frequentemente expõem debug endpoints se não configurados. - Nunca rode como root – crie um usuário não privilegiado no container.
- Habilite TLS em tudo – mesmo em comunicação interna entre serviços (mTLS é o ideal).
- Limite o uso de
unsafe– se você vêimport "unsafe"em código de aplicação, há 99% de chance de ser um risco desnecessário.
Go e a cultura de segurança na Jacobus
Segurança não é um checklist. É uma mentalidade que começa na revisão de código. Em nossos projetos, cada PR passa por uma lista de verificação de segurança mínima:
- Input sanitizado?
- Timeout configurado?
- Sem segredos hardcoded?
- Dependências atualizadas?
- Teste de concorrência (-race) passou?
Além disso, realizamos testes de penetração periódicos – mas o que realmente faz a diferença é a prevenção diária.
Conclusão: segurança é um processo, não um produto
Integrar segurança ao DNA do código significa aceitar que não existe “final” – é um ciclo contínuo de melhoria. Go, com seu ecossistema de ferramentas e sua cultura de simplicidade, é uma base excelente para construir software seguro.
Na Jacobus Software, não esperamos o ataque acontecer para agir. Construímos com segurança desde a primeira linha, em Go, e ensinamos nossos clientes a fazer o mesmo.
Seu software pode ser rápido, escalável e seguro ao mesmo tempo. Basta começar do jeito certo.
🔒 Quer uma análise de segurança no seu código Go?
Nossos especialistas revisam sua base, aplicam as ferramentas corretas e implementam as práticas que eliminam riscos antes de chegar em produção.
Gostou? Compartilhe com seu time de engenharia.
E acompanhe o blog para mais conteúdos sobre Go, performance, arquitetura e segurança.
