O alarme apontou para o vizinho — quando a etiqueta da porta mente sobre o serviço
Segurança·

O alarme apontou para o vizinho — quando a etiqueta da porta mente sobre o serviço

6 min de leitura← Voltar para timeline

O alarme estava certo. O endereço, não.

O relatório de exposição da madrugada de 17 de outubro trouxe quatro linhas vermelhas. Uma delas apontava um serviço conhecido, com nome e sobrenome, escutando em todas as interfaces da máquina.

Fui conferir antes de agir. Naquela porta quem respondia era outro processo — um serviço interno de embeddings, sem autenticação de nenhum tipo. O serviço nomeado no alarme existia, mas escutava só em loopback, numa porta diferente da que o relatório dizia. A migração de máquina tinha trocado os endereços semanas antes; a etiqueta, não.

Isso muda o trabalho por inteiro. Um alarme com endereço errado manda você consertar a porta do vizinho enquanto a sua continua aberta — e ainda entrega a sensação de dever cumprido quando o vermelho vira verde.

A etiqueta que envelheceu

O inventário carrega um mapa estático de porta para serviço, escrito à mão quando a topologia era outra. Toda vez que uma peça muda de lugar — nesse dia tinham mudado duas, numa migração de host — o mapa vira resíduo. O número continua exato. O nome, não.

A ordem certa, que passou a valer depois disso, é não confiar no rótulo:

  • Identidade, não endereço. Verificar quem responde de verdade, comparando o corpo da resposta e não só o código HTTP. Um 200 não diz que serviço atendeu.
  • Loopback por padrão. Serviço que só serve consumidor local não tem motivo para escutar em todas as interfaces.
  • Exceção declarada, com prova datada. Binds de LAN por design entram numa lista de aceitos, cada um com motivo e data. O que é aceito fica separado do que é exposto — senão o vermelho perde sentido.

Depois da cura, o relatório saiu de 12 achados para 6, todos exposição real. Os 26 registros de porta desconhecida em loopback viraram informativos e 11 binds passaram a aceitos por design. Hoje são 43 serviços mapeados.

A segunda mentira, por omissão

Na mesma madrugada, o mesmo relatório dizia, no topo: “nenhum leak real detectado nos seis projetos”.

Cinco dos seis repositórios nunca tinham sido lidos: o scanner procurava os projetos num diretório que a migração deixou para trás e recebia Path not found em cinco de seis — e ainda carimbava o resumo como limpo. Pior, a varredura chamava um transporte de outro sistema operacional, um shim que não existe mais nesta máquina. O silêncio dele era o silêncio do erro.

Antes de consertar, provei que o scanner funcionava: plantei um segredo de formato conhecido num repositório descartável — 1 achado, no tipo certo. No repositório real, 19 achados brutos em cerca de 0,6 segundo. O binário estava bom; o caminho e o transporte é que estavam mortos.

A defesa que ficou: projeto não escaneado agora é estado de primeira classe. Ele vira NAO VERIFICAVEL no resumo, com severidade própria, e o resumo nunca mais pode dizer “limpo” com repositório fora da leitura. Ausência de prova nunca é prova de sucesso.

Ruído que se aprende a ignorar é a terceira mentira

Os 19 achados brutos vinham todos do mesmo arquivo: um artefato local, fora do git. Nada vazava. Se cada um virasse alerta, em uma semana eu teria aprendido a ignorar alerta — e ruído ignorado é gate cego.

A classificação ficou assim:

Situação Classificação Efeito
Segredo em arquivo versionado crítico alerta
Segredo em artefato local, fora do git local contado, sem alerta
Projeto fora da leitura não verificável alerta sempre
Mesma porta com bind novo já visto silêncio (ledger)

Junto vieram os detalhes que fazem um cron sobreviver: saída vazia é silêncio; código de saída sempre zero, porque o scanner devolve erro quando acha o que procura; e o wrapper limpa o PYTHONPATH antes de subir, para o processo não herdar bibliotecas de outro ambiente. São 10 controles automatizados provando o comportamento: repo limpo cala, segredo versionado grita, projeto ausente avisa. Uma revisão independente deu 95 de 100.

Onde estava o risco de verdade

Fecha o caso a lição mais desconfortável: o que estava aberto não era o serviço famoso do alarme, era o encanamento. Dois processos de embeddings — um deles sem autenticação — escutando para a rede inteira, servindo um motor de busca e uma API. Nenhum tem painel, nenhum tem login: são “infraestrutura invisível”.

Movi os dois para loopback com uma sobrescrita de unidade do gerenciador de serviços. O rollback é apagar a sobrescrita, recarregar e reiniciar — documentado no mesmo commit. Validei os consumidores: a busca de memória voltou resultado (score 0,855), a API respondeu saudável e o log do container ficou limpo.

O que vem a seguir

Restam quatro exposições que precisam de decisão, uma a uma: o serviço de área de trabalho remota da estação, dois containers de aplicação que publicam mais do que deveriam e a porta ponto a ponto do cliente de torrent, aberta por natureza. Cada uma é uma decisão com dono e data, não um sed automático.

E fica a pendência que o caso criou: transformar NAO VERIFICAVEL em alerta que acorda alguém. Hoje o resumo registra o projeto fora da leitura, mas quem lê o resumo sou eu, passando os olhos de manhã. Isso é hábito, não sistema — e hábito não sobrevive a semana ruim.

# 1. o scanner acha o que eu plantei de proposito?
gitleaks detect --source /tmp/isca --report-format json

# 2. identidade, nao etiqueta: quem responde naquela porta?
ss -tlnp | grep '<porta>'
curl -sS -X POST "http://127.0.0.1:<porta>/embeddings" -o /tmp/resp.json -w '%{http_code}\n'

# 3. depois da cura: silencio com tudo verificado e limpo
./vigia-de-segurancas.sh --alerta-somente; echo "exit=$?"

Leia também

Mesmo projeto, mesma trilha — as histórias se conectam.

Próximo passo

Se isto te serviu, tem mais: escrevo sobre o mesmo assunto nos outros projetos, e a loja tem as ferramentas que eu uso aqui.

Sem spam, descadastro de um clique. Também estou aqui: Loja de skills · Portfólio