Blog
Segurança

As camadas de segurança do Simmetric Chat: chaves de API, webhooks assinados e DLP

Como o Simmetric Chat autentica cada requisição, faz hash das chaves de API com HMAC-SHA256, assina webhooks e Web Push e redige dados pessoais com filtros DLP.

Simmetric Team10 min de leitura08/09/2026

Segurança é uma pilha, não um interruptor

Uma plataforma de chat que custodia os documentos da sua empresa precisa conquistar confiança em camadas: como as requisições se autenticam, como o acesso programático é emitido e conservado, como as integrações em segundo plano provam sua legitimidade e o que acontece com os conteúdos sensíveis enquanto atravessam prompts e respostas. O Simmetric Chat aborda cada um desses aspectos com um mecanismo nomeado, e a v0.22 fechou algumas das lacunas mais sutis - comparações timing-safe de segredos, login resistente a enumeração e um motor DLP que agora cobre também os identificadores europeus estruturados. Este artigo percorre a pilha da porta de entrada para dentro.

Três formas pelas quais as requisições se autenticam

Cada endpoint sob /api cai em um de três regimes de credenciais:

  • JWT Bearer (primário). Usuários humanos se autenticam pelo endpoint de login ou registro e recebem um JWT assinado. Cada token carrega um claim jti verificado contra uma lista de revogação (opcionalmente apoiada no Redis), para que a desconexão ou a revogação administrativa tenham efeito imediato, não no vencimento. Tokens inválidos ou expirados recebem um 401 limpo; o middleware resolve o usuário junto com papéis e permissões em cada requisição.
  • Chave de API (`X-Api-Key`). O acesso programático - a superfície de conta de serviço do widget e as chaves criadas pelos usuários via os endpoints API-key - usa chaves prefixadas verificadas contra um digest HMAC, descritas abaixo.
  • Segredo compartilhado do collector. As chamadas serviço-a-serviço do collector de ingestão carregam X-Collector-Secret, comparado em tempo constante com uma guarda de comprimento. Este era o último lugar onde sobrevivia uma comparação em claro de segredos no servidor, e a v0.22 o fechou: os callbacks de importação de arquivos agora usam a mesma disciplina crypto.timingSafeEqual de qualquer outra barreira de segredos.

Acima da autenticação ficam as guardas RBAC tratadas em um artigo separado - controles de permissões, barreiras admin e prevenção de IDOR no acesso a workspaces e projetos. A autenticação responde a "quem é você"; o RBAC responde a "o que você pode tocar".

Chaves de API: HMAC-SHA256, criptografadas em repouso

Uma chave de API é uma credencial portadora, então a forma como o servidor a conserva importa tanto quanto a forma como a verifica. O Simmetric Chat emite chaves com um prefixo sk- reconhecível - familiar aos ecossistemas de ferramentas que a maioria dos desenvolvedores já usa - e nunca conserva a chave em si. Em repouso, cada chave existe apenas como digest HMAC-SHA256 calculado sob um segredo dedicado do lado do servidor, API_KEY_HMAC_SECRET:

text
sk-abc123… (emitida uma vez, mostrada uma vez ao chamador)
 │  HMAC-SHA256(API_KEY_HMAC_SECRET, chave)
 ▼
key_hash conservado em api_keys - a chave em si é irrecuperável

O design tem duas propriedades deliberadas:

  • Rotação desacoplada. API_KEY_HMAC_SECRET é independente de JWT_SECRET e de ENCRYPTION_KEY. Rotacionar a chave de assinatura das sessões não invalida as chaves de API, e rotacionar a chave de criptografia em repouso não quebra a verificação de chaves. Cada segredo tem uma única tarefa.
  • Verificação em tempo constante. A verificação é uma busca do digest HMAC com chave - O(1), sem limites take sobre uma varredura de candidatos. É o que torna a autenticação por chave de API barata o suficiente para estar em cada requisição numa implantação multi-instância.

Os usuários gerenciam suas próprias chaves via os endpoints API-key: criação sob demanda, listagem sob demanda, revogação sob demanda. A revogação elimina a capacidade de reconstruir uma credencial válida; o digest não corresponde mais a nada.

Webhooks assinados e Web Push

As integrações de saída devem ser verificáveis tanto quanto as de entrada.

Os webhooks são assinados com HMAC-SHA256. O servidor calcula uma assinatura sobre o payload usando o segredo do webhook, e o seu serviço receptor recalcula o digest antes de confiar no corpo do evento. Um endpoint receptor nunca deve confiar num chamador que se diz Simmetric Chat - ele pode provar isso, byte a byte, com a própria cópia do segredo. Um endpoint de eventos de teste permite exercitar um receptor sem gerar atividade real na plataforma.

O Web Push usa o protocolo VAPID para notificações do navegador. O servidor detém um par de chaves VAPID; a chave pública é exposta aos clientes autenticados via um endpoint de sistema, as assinaturas são gerenciadas por endpoints explícitos de subscribe/unsubscribe, e os administradores podem enviar um push de teste para verificar o pipeline de ponta a ponta. Ambos os canais estão sempre ativos no nível Community - assinatura e push são comportamento base da plataforma, não funcionalidade enterprise.

Rate limiting na fronteira

O rate limiting é estratificado por superfície, com os costumeiros cabeçalhos RateLimit-* emitidos nas rotas limitadas:

  • Limiter global de API - 200 requisições por minuto por IP em todas as rotas em produção
  • Limiter de autenticação - 10 requisições por minuto nos endpoints de escrita da autenticação, a barreira mais estreita porque os endpoints de credenciais são os primeiros alvos dos abusos
  • Limiter de leads do widget - 3 requisições por hora na captura de leads, porque um formulário público é onde o abuso automatizado se concentra
  • Limiter de probe - 10 requisições por minuto nos endpoints de probe de conectividade, para que o teste do assistente de configuração não possa ser transformado em arma

Quando REDIS_URL está configurado, os contadores vivem num store Redis compartilhado para que os limites signifiquem a mesma coisa em cada instância; caso contrário, cada instância mantém seu próprio store. As requisições que carregam um cabeçalho de widget pulam o limiter global - o tráfego de widgets já vem throttled a montante pelo limiter por chave do serviço de widget - e não há um limiter dedicado ao chat, porque o agente impõe internamente concorrência por usuário, orçamentos de token e timeouts de relógio de parede.

DLP: redação antes da exfiltração

A prevenção de perda de dados no Simmetric Chat é um plugin de filtro que escaneia tanto o prompt de entrada quanto a resposta de saída - incluindo os flushes progressivos token a token do streaming - e redige as correspondências antes que o conteúdo saia da sua rede. O scanner reconhece 10 classes de patterns de PII integrados:

  • Endereços de email
  • Números de cartão de crédito
  • Chaves de API e chaves privadas
  • Mais os identificadores europeus estruturados: Partita IVA italiana, codice fiscale e IBAN, adicionados na v0.22 e semeados de forma idempotente

A configuração de patterns é respaldada por banco de dados e gerenciada por admins: ativar ou desativar qualquer pattern por linha, adicionar até 50 patterns personalizados com validação de compilação ao vivo e prévia de teste, e inspecionar um painel de histórico de correspondências DLP filtrável por origem (chat ou widget). As expressões regulares integradas são congeladas - você pode desativar um pattern integrado mas não reescrevê-lo - enquanto os patterns personalizados carregam suas definições. Os escaneamentos que conseguem ler os patterns configurados os usam por um cache de TTL curto e recuam para o conjunto integrado se o banco de dados estiver inalcançável, para que uma interrupção do banco nunca desative a redação.

Dois detalhes de governança completam o quadro. Um ajuste DLP_BYPASS_ROLES permite aos admins isentar papéis específicos do escaneamento, e cada bypass gera um evento de auditoria registrando quem bypassou e em qual superfície - nunca o conteúdo escaneado. Os administradores também podem revelar ou voltar a ocultar os textos correspondentes através de uma conversa com um único interruptor, com visibilidade limitada à sessão e oculta por padrão, para que a redação continue reversível para uma revisão autorizada, mas não em silêncio.

O endurecimento mais sutil da v0.22

As pequenas mudanças importam porque fecham os canais que os atacantes realmente sondam:

  • Comparações timing-safe em todos os lugares. Cada comparação em claro de segredos que restava - as barreiras do segredo do collector, o callback de importação de arquivos, o controle de chave cache-bust do widget - agora usa crypto.timingSafeEqual com uma guarda de comprimento e falha em modo fechado quando o segredo esperado não está definido.
  • Login resistente a enumeração. Quando um nome de usuário não existe, o login executa de todo modo uma comparação fictícia de hash antes de responder, para que o tempo de resposta não distinga mais os usuários existentes dos inexistentes. Os corpos inválidos devolvem um 400 estruturado em vez de um 401 que deixaria vazar os internos do Zod.
  • Configurações erradas que falham em voz alta. Uma má configuração HMAC do lado do servidor na verificação de chaves de API devolve 500, por escolha - um segredo mal configurado nunca deve se disfarçar de falha de autenticação.
  • Validação estruturada. Os corpos das requisições são validados com schemas Zod compartilhados via safeParse; cada erro é um envelope uniforme com detalhes por campo, para que os clientes falhem de forma previsível.

Toda a superfície de API - tabelas de endpoints, enquadramento dos eventos SSE e requisitos de autenticação por rota - está documentada na referência de API, e uma interface Swagger ao vivo está incluída no servidor.

Leia o guia completo na documentação →

Artigos relacionados