---
title: "cargo-geiger: Audite Unsafe em Rust | Rust Brasil"
url: "https://rustlang.com.br/blog/cargo-geiger-unsafe-rust-dependencias-2026/"
markdown_url: "https://rustlang.com.br/blog/cargo-geiger-unsafe-rust-dependencias-2026.MD"
description: "Use cargo-geiger para mapear unsafe no código Rust e nas dependências. Guia com interpretação, triagem, CI, Miri, supply chain, políticas e boas práticas."
date: "2026-08-22"
author: "Equipe Rust Brasil"
---

# cargo-geiger: Audite Unsafe em Rust | Rust Brasil

Use cargo-geiger para mapear unsafe no código Rust e nas dependências. Guia com interpretação, triagem, CI, Miri, supply chain, políticas e boas práticas.


**Use `cargo-geiger` para descobrir onde existe `unsafe` no seu projeto Rust e no grafo de dependências antes de começar uma auditoria manual.** O fluxo básico é instalar o subcomando, executá-lo na raiz do repositório e tratar o resultado como um mapa de revisão — não como um placar automático de segurança.

```bash
cargo install --locked cargo-geiger
cargo geiger
```

A ferramenta lista estatísticas relacionadas ao uso de Rust `unsafe` na crate atual e em suas dependências. Isso ajuda a responder perguntas importantes: o código do produto contém blocos `unsafe`? Uma crate transitiva concentra operações de baixo nível? Uma atualização aumentou a superfície que exige confiança? Quais pacotes devem receber revisão mais cuidadosa?

A interpretação correta é essencial. **Encontrar `unsafe` não prova vulnerabilidade, e encontrar zero ocorrências não prova segurança.** Unsafe é parte legítima da linguagem para FFI, alocadores, runtimes, drivers, bindings, acesso ao sistema operacional e abstrações eficientes. O valor do `cargo-geiger` está em tornar essa superfície visível e comparável.

## Resposta rápida: como usar cargo-geiger

| Etapa | Comando ou ação | Objetivo |
|---|---|---|
| Instalar | `cargo install --locked cargo-geiger` | Adicionar o subcomando localmente |
| Executar | `cargo geiger` | Analisar o pacote e as dependências |
| Confirmar opções | `cargo geiger --help` | Ver flags da versão instalada |
| Localizar origem | `cargo tree -i nome-da-crate` | Descobrir quem introduziu uma dependência |
| Revisar advisories | `cargo audit` | Consultar vulnerabilidades conhecidas |
| Exercitar unsafe | `cargo +nightly miri test` | Procurar classes de comportamento indefinido nos testes |
| Revisar política | `cargo deny check` | Validar fontes, licenças, bans e advisories configurados |
| Comparar mudança | salvar relatórios antes/depois | Detectar crescimento da superfície de unsafe |

O comando e o formato do relatório podem evoluir. Antes de criar parsing, thresholds ou automação de CI, fixe uma versão homologada e leia `cargo geiger --help` no ambiente que executará a análise.

## O que `unsafe` significa em Rust

Rust seguro impede várias classes de erro por meio do sistema de tipos, ownership, borrowing e verificação de lifetimes. Ainda assim, algumas operações não podem ser provadas pelo compilador com as regras normais. Um bloco ou função `unsafe` permite assumir responsabilidade manual por invariantes específicas.

Entre as operações associadas a unsafe estão:

- desreferenciar raw pointers;
- chamar funções `unsafe`;
- acessar determinados estados globais mutáveis;
- implementar traits `unsafe`;
- acessar campos de unions;
- atravessar fronteiras FFI nas quais o compilador não conhece o contrato externo.

O restante do sistema de tipos continua ativo. `unsafe` não transforma Rust em uma linguagem sem regras; ele cria uma fronteira em que o programador precisa provar condições que o compilador não consegue verificar.

O guia de [Unsafe Rust](/artigos/unsafe-rust/) explica essas operações em profundidade. Para uma auditoria, a pergunta não é apenas “quantas linhas unsafe existem?”, mas **quais invariantes elas assumem, quem as mantém e qual API segura depende delas?**

## Instalando cargo-geiger

A instalação padrão documentada pelo projeto é:

```bash
cargo install --locked cargo-geiger
```

Depois, confirme a versão e a ajuda local:

```bash
cargo geiger --version
cargo geiger --help
```

Em alguns ambientes, a compilação da ferramenta pode depender da disponibilidade de OpenSSL no sistema. O projeto também documenta uma instalação que compila e vincula uma cópia vendorizada:

```bash
cargo install --locked cargo-geiger --features vendored-openssl
```

Não adote essa variante automaticamente em todo ambiente. Em estações e runners administrados, uma biblioteca de sistema atualizada pode ser preferível. Em uma imagem de CI mínima, a opção vendorizada pode simplificar a instalação. A decisão deve considerar tempo de build, política de dependências nativas e reprodutibilidade.

Para pipelines, evite instalar “a versão mais nova disponível” em toda execução sem controle. Fixe a versão validada pelo time, porque mudanças no analisador ou na apresentação podem quebrar scripts e alterar a baseline sem que o código do produto tenha mudado.

## Executando a primeira análise

Entre no diretório que contém o `Cargo.toml`:

```bash
cd meu-projeto
cargo geiger
```

Faça a primeira execução em um repositório limpo e registre o contexto:

```bash
git status --short
rustc --version
cargo geiger --version
cargo geiger
```

Essas informações ajudam a reproduzir o resultado. O grafo analisado pode variar com:

- versão do compilador e do Cargo;
- conteúdo do `Cargo.lock`;
- features ativadas;
- target e sistema operacional;
- membros selecionados em um workspace;
- dependências de desenvolvimento e build;
- configuração do ambiente.

Se o projeto não versiona o `Cargo.lock`, duas execuções em momentos diferentes podem resolver conjuntos distintos de dependências. Para aplicações, serviços e CLIs, normalmente vale versionar o lockfile e usar builds com `--locked` conforme a política do repositório.

## Como interpretar o relatório sem tirar conclusões erradas

O relatório aponta ocorrências e estatísticas de unsafe, mas não conhece o contrato completo de cada crate. Uma dependência com operações de baixo nível pode ter revisão rigorosa, testes extensos e uma API pública segura. Outra pode ter poucas ocorrências, mas invariantes frágeis e manutenção abandonada.

Classifique os resultados em camadas.

### 1. Código local do produto

Unsafe escrito pela própria equipe merece uma revisão direta porque você controla a implementação. Para cada bloco ou função, verifique:

- existe uma alternativa safe na biblioteca padrão ou em uma crate madura?
- o bloco possui o menor escopo possível?
- as pré-condições estão documentadas em uma seção `# Safety`?
- a API pública impede que chamadores safe violem invariantes?
- existem testes de fronteira e entradas adversas?
- Miri consegue executar a parte relevante da suíte?
- outro desenvolvedor revisou a lógica de ponteiros, aliasing, inicialização e lifetimes?

Um bloco curto não é automaticamente simples. Uma única conversão incorreta pode introduzir comportamento indefinido. Da mesma forma, uma implementação longa pode ser bem encapsulada e auditada. Contagem ajuda a localizar; revisão determina o risco.

### 2. Dependências diretas

Para crates declaradas no seu `Cargo.toml`, você pode avaliar:

- por que a dependência foi escolhida;
- se o unsafe está ligado a uma feature opcional;
- se existe uma alternativa com superfície menor;
- se a crate documenta sua política de segurança;
- se recebe atualizações e correções;
- se há advisories conhecidos;
- se a API usada pelo projeto atravessa a parte unsafe.

Não troque uma crate madura apenas para reduzir uma contagem. Reimplementar parsing, criptografia, concorrência ou FFI dentro do produto pode aumentar o risco real, mesmo que o relatório fique aparentemente menor.

### 3. Dependências transitivas

Quando uma crate inesperada aparece, descubra quem a trouxe:

```bash
cargo tree -i nome-da-crate
```

O guia de [`cargo tree`](/blog/cargo-tree-grafo-dependencias-rust-2026/) mostra como investigar caminhos, versões duplicadas e features. O resultado pode revelar que:

- uma feature padrão ativou um backend nativo;
- uma dependência de desenvolvimento trouxe tooling adicional;
- duas versões da mesma crate estão resolvidas;
- um pacote do workspace introduziu a dependência para todos;
- o componente existe apenas em determinado target.

A ação correta pode ser desativar uma feature, atualizar a dependência direta, isolar um pacote ou simplesmente documentar por que a cadeia é aceita.

## Unsafe não é sinônimo de vulnerabilidade

Um erro comum é tratar qualquer ocorrência como defeito. Isso produz incentivos ruins: esconder o uso, substituir bibliotecas testadas por código próprio ou escolher abstrações menos adequadas apenas para chegar a zero.

Unsafe é esperado em áreas como:

- bindings para C e APIs do sistema operacional;
- runtimes assíncronos e primitivas de sincronização;
- estruturas de dados com layout especializado;
- drivers e sistemas embarcados;
- SIMD e otimizações específicas de arquitetura;
- alocação e gerenciamento de memória;
- bibliotecas que encapsulam ponteiros em APIs safe;
- kernels, hipervisores e componentes `no_std`.

A metáfora do nome “Geiger” é útil: a ferramenta detecta uma superfície que pede atenção, como um contador detecta radiação. Ela não explica sozinha a fonte, a dose aceitável ou a proteção existente.

Uma política madura evita dois extremos:

- **“Unsafe é sempre ruim.”** Ignora que a própria infraestrutura de baixo nível precisa dele.
- **“Rust garante segurança, então unsafe não importa.”** Ignora que as garantias dependem da correção das fronteiras unsafe.

## Comparando relatórios antes e depois de uma mudança

Uma aplicação prática é revisar o impacto de uma atualização de dependências. Salve uma baseline:

```bash
cargo geiger > /tmp/geiger-antes.txt
```

Atualize a crate ou o lockfile de forma controlada e gere outro relatório:

```bash
cargo geiger > /tmp/geiger-depois.txt
diff -u /tmp/geiger-antes.txt /tmp/geiger-depois.txt
```

O diff pode indicar:

- nova dependência que usa unsafe;
- remoção de uma implementação antiga;
- troca de backend por feature;
- crescimento no código local;
- mudança ampla causada por uma atualização aparentemente pequena.

Não transforme o texto bruto em uma API estável sem verificar o suporte da versão usada. Para revisão humana dentro do mesmo ambiente, o diff já é valioso. Para dashboards e gates duradouros, avalie os formatos e bibliotecas serializáveis expostos pelo ecossistema do projeto, fixando versões e testes para o parser.

Combine essa comparação com [cargo-outdated](/blog/cargo-outdated-dependencias-rust-atualizar-2026/) e revisão do `Cargo.lock`. O objetivo é explicar a mudança, não impedir toda evolução do grafo.

## cargo-geiger, Miri, cargo-audit e cargo-vet

Essas ferramentas são complementares porque observam dimensões diferentes.

| Ferramenta | Pergunta principal |
|---|---|
| `cargo-geiger` | onde existe uso estatístico de unsafe? |
| Miri | os testes executados violam determinadas regras do modelo de memória? |
| `cargo-audit` | o lockfile contém crates com advisories conhecidos? |
| `cargo-vet` | quais dependências receberam auditorias ou critérios de confiança? |
| `cargo-deny` | o grafo viola políticas de licença, fonte, ban ou advisory? |
| `cargo-tree` | qual caminho introduziu cada dependência? |

### Miri

Miri interpreta MIR e consegue detectar determinadas classes de comportamento indefinido nos caminhos exercitados pelos testes:

```bash
rustup +nightly component add miri
cargo +nightly miri test
```

Ele não prova ausência de bugs em caminhos não executados e nem todo código, FFI ou operação de plataforma é compatível com o ambiente interpretado. Ainda assim, é uma ferramenta importante para testar abstrações unsafe. Veja o guia de [Miri em Rust](/blog/miri-rust-undefined-behavior-2026/).

### cargo-audit

`cargo-audit` consulta advisories conhecidos para versões presentes no lockfile. Uma crate pode usar unsafe e não ter advisory; outra pode ser escrita sem unsafe e possuir uma vulnerabilidade lógica ou de protocolo. Por isso, rode [cargo-audit](/blog/cargo-audit-vulnerabilidades-dependencias-rust-ci-2026/) separadamente.

### cargo-vet

O [cargo-vet](/blog/cargo-vet-auditoria-dependencias-rust-supply-chain-2026/) ajuda organizações a registrar auditorias e critérios de confiança sobre dependências. `cargo-geiger` pode orientar prioridade: componentes de baixo nível e crates transitivas críticas merecem uma trilha de confiança mais explícita.

### cargo-deny e SBOM

O guia de [supply chain Rust com cargo-deny e SBOM](/blog/rust-seguranca-supply-chain-cargo-deny-sbom-2026/) amplia a análise para licenças, fontes, versões banidas e inventário. Unsafe é apenas uma dimensão da dependência; procedência e manutenção também importam.

## Política para código local: `forbid(unsafe_code)` ou unsafe revisado

Projetos que não precisam de operações de baixo nível podem declarar uma regra forte:

```rust
#![forbid(unsafe_code)]
```

Isso impede que o código sob aquela configuração use unsafe. É uma boa escolha para aplicações de domínio, serviços CRUD e bibliotecas que conseguem cumprir seu contrato usando apenas Rust safe.

Mas `forbid(unsafe_code)` não significa que todas as dependências sejam livres de unsafe. O atributo governa o código em que é aplicado, não reescreve o ecossistema inteiro. É justamente aí que `cargo-geiger` acrescenta contexto sobre o grafo.

Para projetos que precisam de unsafe, uma política possível é:

1. negar unsafe por padrão em módulos comuns;
2. concentrar exceções em um módulo pequeno;
3. documentar invariantes com `# Safety`;
4. oferecer uma API safe aos consumidores;
5. exigir revisão adicional para mudanças no módulo;
6. executar Miri e testes de propriedade quando aplicável;
7. acompanhar o relatório do `cargo-geiger` nas atualizações.

A meta não é esconder unsafe, mas **conter responsabilidade**.

## Colocando cargo-geiger na CI

Comece com um job informativo. Ele gera visibilidade sem bloquear o time antes de existir uma baseline entendida.

```yaml
name: unsafe-audit

on:
  pull_request:
  workflow_dispatch:

jobs:
  cargo-geiger:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable

      - name: Instalar cargo-geiger
        run: cargo install cargo-geiger --locked

      - name: Gerar relatório de unsafe
        run: cargo geiger
```

Esse exemplo funciona como ponto de partida conceitual para GitHub Actions e Gitea Actions. Em produção:

- fixe a versão da ferramenta;
- use a estratégia de OpenSSL adequada ao runner;
- preserve o relatório como artefato se o log for insuficiente;
- execute com o conjunto de features e targets relevante;
- defina timeout para instalações e análises;
- valide que o comando cobre os membros esperados do workspace;
- não interprete qualquer número positivo como falha.

Depois de algumas execuções, o time pode adotar uma política de mudança:

- novo unsafe no código local exige justificativa e revisão;
- nova dependência de baixo nível exige triagem;
- crescimento inesperado no relatório exige explicação;
- exceções aceitas ficam documentadas;
- pacotes críticos recebem Miri, fuzzing ou auditoria adicional.

Um gate baseado apenas em “contagem deve ser zero” funciona para poucos projetos. Um gate baseado em **mudança não explicada** costuma ser mais útil em sistemas reais.

## Workspaces, features e targets

O resultado precisa representar o artefato que você entrega. Em um workspace, uma CLI administrativa pode depender de componentes diferentes da biblioteca pública ou do serviço principal.

Antes de automatizar, verifique na ajuda da versão instalada como selecionar pacotes e opções de Cargo. Também compare as configurações suportadas pelo projeto:

- features padrão;
- `--no-default-features` quando essa combinação é válida;
- features de TLS, banco, runtime ou bindings;
- targets Linux, Windows, macOS, WASM e embedded;
- dependências normais, de desenvolvimento e de build.

Uma análise no notebook Linux não representa necessariamente o binário Windows nem o firmware `no_std`. Dependências condicionais podem concentrar unsafe justamente no target que não foi analisado.

Use `cargo tree --target ...` e a matriz de CI para entender as diferenças. Para testar combinações de features, o [cargo-hack](/blog/cargo-hack-features-powerset-ci-rust-2026/) ajuda a manter a matriz explícita.

## Triagem prática de uma dependência com unsafe

Quando o relatório destacar uma crate, siga um processo reproduzível.

### 1. Descubra o caminho

```bash
cargo tree -i crate-destacada
```

### 2. Entenda a função no produto

Ela implementa TLS, parsing, FFI, compressão, acesso ao kernel, armazenamento ou apenas uma ferramenta de desenvolvimento?

### 3. Revise features

A crate entra por uma feature necessária? Existe backend alternativo? Desativar defaults remove funcionalidade importante?

### 4. Consulte manutenção e advisories

Verifique releases, changelog, repositório, issues relevantes e RustSec. Não confunda ausência de advisory com auditoria concluída.

### 5. Procure encapsulamento

O unsafe está restrito a uma camada pequena com API safe? As invariantes são documentadas? Existem testes, fuzzing e uso de Miri?

### 6. Compare alternativas pelo risco total

Considere maturidade, performance, compatibilidade, manutenção, licença e custo de migração. “Menos unsafe” é um critério; não é o único.

### 7. Registre a decisão

Uma issue, ADR ou comentário de dependência pode explicar por que a crate foi aceita, quais controles existem e quando a escolha será revista.

## Armadilhas comuns

### Usar o relatório como ranking de crates “boas” e “ruins”

Contagem não mede qualidade de invariantes, revisão ou impacto no produto. Use-a para prioridade, não para reputação.

### Remover uma dependência madura e reescrever o código

Você pode trocar unsafe auditado por bugs lógicos, parsing incorreto ou uma nova implementação sem testes. Compare risco total.

### Analisar somente o código local

Grande parte da superfície de baixo nível pode estar nas transitivas. O grafo resolvido importa.

### Ignorar features e targets

O relatório pode variar de acordo com a configuração. Audite o que realmente é compilado e entregue.

### Falhar a CI sem baseline

A equipe recebe um número vermelho sem saber se houve regressão. Comece informativo, classifique e só então defina gates.

### Tratar zero unsafe como prova de segurança

Erros de autenticação, autorização, criptografia, lógica, protocolo e configuração podem existir em Rust totalmente safe.

### Tratar qualquer unsafe como vulnerabilidade

Unsafe pode ser necessário e corretamente encapsulado. A investigação precisa chegar às invariantes e ao uso concreto.

## Checklist de auditoria

- [ ] instalar uma versão controlada do `cargo-geiger`;
- [ ] executar na raiz correta e registrar toolchain;
- [ ] distinguir código local, dependências diretas e transitivas;
- [ ] localizar caminhos com `cargo tree -i`;
- [ ] revisar features e targets realmente entregues;
- [ ] verificar advisories com `cargo-audit`;
- [ ] examinar manutenção, documentação e política de segurança;
- [ ] conferir se unsafe está encapsulado por APIs safe;
- [ ] exigir documentação `# Safety` no código local;
- [ ] executar Miri nos testes compatíveis;
- [ ] usar proptest ou fuzzing em parsers e invariantes complexas;
- [ ] comparar relatórios antes e depois de atualizações;
- [ ] documentar exceções e decisões de dependência;
- [ ] começar a CI em modo informativo;
- [ ] bloquear apenas violações de uma política compreendida.

## cargo-geiger para carreira e portfólio Rust

Em um projeto de portfólio, executar a ferramenta é menos importante do que explicar a decisão. Um README técnico pode mostrar:

- baseline do código local e das dependências;
- uma crate transitiva investigada com `cargo tree -i`;
- justificativa para uma fronteira FFI;
- módulo que encapsula raw pointers em API safe;
- testes com Miri;
- `cargo-audit` e `cargo-deny` na CI;
- política para novos blocos unsafe;
- comparação do relatório após uma atualização.

Esse material demonstra repertório de engenharia de sistemas, segurança e supply chain. Ele é relevante para [vagas Rust](/vagas/) em infraestrutura, embedded, segurança, bancos de dados, runtimes, developer tooling e plataformas de alta performance. O guia de [carreira em segurança com Rust](/carreira/nicho-seguranca/) ajuda a conectar essas ferramentas a projetos e responsabilidades profissionais.

Não apresente a conclusão “minhas dependências são seguras porque o relatório tem pouco unsafe”. Uma formulação madura seria: “mapeei a superfície, investiguei os caminhos críticos, documentei invariantes, executei controles complementares e defini quando a análise precisa ser repetida”.

## Perguntas frequentes

### Para que serve cargo-geiger?

Ele lista estatísticas relacionadas ao uso de unsafe no pacote e nas dependências. O relatório orienta auditoria, comparação e triagem de supply chain.

### Como instalar?

```bash
cargo install --locked cargo-geiger
cargo geiger
```

Se o ambiente precisar de OpenSSL vendorizado, consulte a variante documentada pelo projeto e valide o impacto no runner.

### Uma crate com unsafe é insegura?

Não. Avalie por que ela usa unsafe, como as invariantes são encapsuladas, maturidade, testes, manutenção, advisories e o caminho pelo qual entra no produto.

### cargo-geiger substitui Miri?

Não. `cargo-geiger` mapeia ocorrências; Miri executa caminhos de teste e procura determinadas violações do modelo de memória. Use os dois quando o risco justificar.

### Devo bloquear a CI?

Comece com relatório informativo. Depois bloqueie mudanças que violem uma política explícita — por exemplo, novo unsafe local sem documentação e revisão — em vez de reprovar qualquer contagem positiva.

## Conclusão

`cargo-geiger` torna visível uma parte crítica da confiança em Rust: as fronteiras onde o compilador delega invariantes ao programador e as dependências que implementam operações de baixo nível.

O fluxo recomendado é simples: **gere uma baseline, separe código local de dependências, encontre os caminhos com `cargo tree`, revise contexto e combine o resultado com Miri, RustSec e políticas de supply chain**. Não persiga zero como métrica universal e não ignore crescimento sem explicação.

Comece com:

```bash
cargo install --locked cargo-geiger
cargo geiger
cargo tree -i crate-que-voce-quer-investigar
```

Depois documente uma decisão real. Essa é a diferença entre apenas executar uma ferramenta e construir uma prática de auditoria: o relatório vira entrada para revisão, testes e manutenção contínua, não um selo automático de segurança.
