Seu endereço está na allowlist — isso faz do remetente você?


Você conecta uma caixa de entrada ao Hermes com uma allowlist que contém exatamente um endereço — o seu — e considera a porta fechada. Então, um dia, o bot responde a uma mensagem de um domínio que você nunca viu, assinada com o seu nome. A allowlist não estava mal configurada. O problema é que a string que você colocou nela e o “remetente” daquela mensagem nunca foram o mesmo tipo de coisa.

Dois patches de segurança mesclados em 2026-09-27 corrigem esse mesmo erro em dois lugares: o gateway de e-mail e o gateway SimpleX incluído autorizavam remetentes usando um campo que o próprio remetente escreve sobre si mesmo. Ambos são P1 e ambos estão em main hoje.

Um nome de exibição é texto livre: como a allowlist do SimpleX foi burlada

O SimpleX foi feito para privacidade: não há IDs de usuário persistentes. Cada contato recebe um ID interno opaco (contactId) gerado no momento da conexão — essa é a identidade. O nome de exibição é o que a outra parte digitou no próprio cliente.

Antes da correção, a regra de autorização do gateway era “permitir se o contactId ou o nome de exibição do remetente corresponder à allowlist”. Nomes de exibição colidem e podem ser alterados a qualquer momento, então qualquer contato podia definir o próprio nome com um valor que já estava na sua allowlist e começar a comandar seu bot. A brecha foi reportada em 2026-06-12 (#44729) e fechada pelo PR #125034 em 27 de setembro.

O que acontece agora:

  • SIMPLEX_ALLOWED_USERS corresponde apenas a contactIds numéricos; nomes de exibição são ignorados.
  • Ao conectar, o adaptador registra um aviso listando as entradas da allowlist que não parecem IDs de contato, porque essas entradas não fazem mais nada. Muito provavelmente você precisará substituí-las.
  • A documentação, o plugin.yaml e o prompt de hermes gateway setup agora pedem todos IDs de contato.

Para encontrar o seu: inicie o daemon simplex-chat, abra a conversa com seu contato do agente e leia o ID numérico nos logs de sessão — ou rode /contacts no daemon.

E-mail é mais sutil: o segundo endereço dentro do From

O e-mail é pior porque a RFC 5322 permite que From seja “nome de exibição mais endereço”, e o nome de exibição pode conter quase qualquer coisa. O parser antigo pegava o primeiro endereço entre chaves angulares que encontrava:

From: "Victim <[email protected]>" <[email protected]>

O remetente real aqui é [email protected], mas o código antigo resolvia [email protected] — o endereço que está na sua allowlist.

O mesmo patch fecha mais duas formas:

Forma do ataque Antes Depois
Um segundo endereço em From (listas de discussão, grupos, um endereço dentro da parte de exibição) Uma identidade “legítima” era resolvida e autorizada O From resolve vazio e a mensagem é descartada antes da autenticação ou do despacho
Um From enorme ou profundamente aninhado (mais de 2048 caracteres, ou mais de 64 parênteses de comentário) O parsing em Python puro levava segundos com entrada hostil, segurando o GIL Os limites de tamanho e de aninhamento o descartam de imediato — um valor de 200 KB em cerca de 2 ms
Texto controlado pelo remetente dentro do cabeçalho Authentication-Results do servidor receptor (partes locais entre aspas, comentários) Um veredito forjado dmarc=pass / spf=pass podia ser lido As cláusulas são separadas respeitando strings entre aspas e comentários aninhados; uma aspa ou parêntese desbalanceado falha de forma fechada, e cada veredito é lido apenas do seu próprio method=result

Mais um critério mudou: dmarc=pass não é mais aceito por si só. Ele só conta quando o header.from do veredito está alinhado com o domínio do From que foi analisado (iguais, ou um é sufixo com ponto do outro) — caso contrário, basta ao atacante ter um domínio que controle para passar no DMARC e então avalizar qualquer From. Esta é a correção GHSA-rxqh-5572-8m77.

O que sua instalação faz agora

No lado do e-mail, “o remetente precisa estar autenticado” vem ativado por padrão:

# ~/.hermes/config.yaml
platforms:
  email:
    require_authenticated_sender: true   # padrão: true
    authserv_id: "your-mx.example.com"   # opcional: fixa Authentication-Results no seu próprio servidor

A variável de ambiente é EMAIL_AUTHSERV_ID. Se o seu servidor de correio não carimba esse cabeçalho de forma alguma, a saída de emergência documentada é require_authenticated_sender: false (ou EMAIL_TRUST_FROM_HEADER=true) — isso restaura o comportamento antigo, e a documentação diz claramente que significa aceitar o risco. A configuração completa da plataforma de e-mail (variáveis IMAP/SMTP, códigos de pareamento, EMAIL_ALLOWED_USERS) está na documentação de e-mail.

Para as operações diárias do gateway, veja nossa referência do comando hermes gateway. Se você quer a ideia espelhada — autenticidade de saída em vez de entrada —, o post sobre webhooks mostra como o Hermes assina os próprios eventos com HMAC para que os receptores possam verificar a origem.

Uma coisa que não ficou mais rígida: a saída. hermes send --to simplex:alice "hello" continua funcionando por nome de exibição, porque ali é você quem escolhe o destino. O que ficou mais rígido é apenas quem pode dar ordens ao seu agente.

Status de lançamento

Os dois patches foram mesclados em 2026-09-27, depois da tag de release v0.21.5 (v2026.9.24), então por enquanto eles vivem apenas em main: hermes update os traz, ou aguarde a próxima tag.

A conclusão

Uma string em uma allowlist nunca foi uma identidade — é uma linha que outra pessoa escreveu para você ler. Essas correções reancoram o “quem está falando comigo” em algo que o remetente não pode decidir: o contactId gerado no momento da conexão, no SimpleX, e um veredito carimbado pelo seu próprio servidor receptor, no e-mail, além de uma checagem de que o veredito realmente cobre o domínio do From. Se você mesmo roda um bot, vale adotar dois hábitos: substituir entradas da allowlist por IDs de contato reais e fazer seu servidor de correio carimbar cabeçalhos de autenticação em vez de desligar essa confiança.