Proxy de credenciais — técnico
Como o proxy funciona.
Contra o que ele protege. Contra o que ele não protege.
Esta página é para revisores de segurança, testadores de penetração e engenheiros que avaliam o modelo de ameaças do proxy. Ela descreve o que o proxy faz em nível de protocolo, onde as credenciais existem na memória e quais superfícies de ataque permanecem.
Arquitetura
O proxy é um proxy HTTPS MITM baseado em CONNECT. Um agente de IA define HTTPS_PROXY para apontar para ele. Quando o agente faz uma requisição HTTPS, o proxy intercepta a conexão TLS, inspeciona os cabeçalhos da requisição em busca de referências de credenciais, as resolve contra o cofre Clavitor e encaminha a requisição com as credenciais injetadas para a API upstream.
O proxy escuta em 127.0.0.1:1983 por padrão — o padrão sidecar onde o proxy e o agente compartilham um host. Para implantações compartilhadas (um proxy servindo múltiplos agentes em uma rede privada, sidecar de contêiner para múltiplas cargas de trabalho, host de proxy dedicado), a interface de escuta é configurável via CLAVITOR_PROXY_LISTEN.
O proxy é um binário Go autônomo. Sem CGO. Todas as rotas de criptografia de protocolo Clavitor passam por uma implementação canônica em Rust compilada para WebAssembly e carregada via wazero na inicialização.
Tratamento TLS
O proxy gera uma CA raiz ECDSA P-256 autoassinada na primeira execução, persistida no diretório do binário com permissão 0600. Para cada host upstream, um certificado folha é emitido sob demanda, assinado por esta CA e armazenado em cache na memória com expiração limitada (1.000 hosts). Certificados folha são válidos por 24 horas e regenerados transparentemente na marca de 23 horas para evitar expiração no meio da sessão.
O agente deve confiar no certificado CA do proxy. Exporte-o com clavitor-proxy ca.
Conexões upstream usam TLS 1.3 mínimo com negociação ALPN para HTTP/2 e HTTP/1.1. O pool de certificados do sistema é usado para verificação upstream. Sem fixação de certificado — o proxy confia no que o sistema operacional confia.
Credenciais nunca são armazenadas em cache, nunca escritas em disco e nunca mantidas por mais tempo do que uma requisição HTTP.
| Fase | Onde a credencial existe | Duração |
|---|---|---|
| Em repouso no cofre | Texto cifrado AES-GCM no banco de dados do cofre | Até ser excluído |
| Em trânsito para o proxy | Resposta JSON criptografada por TLS da API do cofre | Uma viagem de ida e volta HTTP |
| Descriptografado no proxy | Memória do processo (string Go no heap) | Uma requisição HTTP |
| Injetado na requisição upstream | Bytes criptografados por TLS na rede para o upstream | Uma requisição HTTP |
O proxy mantém a chave de descriptografia de credenciais do agente (16 bytes) na memória durante todo o seu tempo de execução. Ela é carregada da configuração sidecar criptografada (formato CLV1) na inicialização e limpa no desligamento gracioso. A chave nunca sai do processo.
A configuração sidecar é criptografada com AES-128-GCM e HMAC-SHA256 usando chaves determinísticas derivadas de uma semente estática. Isso é ofuscação, não confidencialidade — o limite de segurança são as permissões de arquivo (0600) e a posse do arquivo. O formato CLV1 é compartilhado entre o proxy, o CLI e a extensão do navegador.
Modos de resolução
Modo 1 — placeholder explícito
O agente inclui uma referência clavitor://Entrada/campo em um cabeçalho de requisição. O proxy busca no cofre a entrada pelo nome, a obtém, descriptografa o campo nomeado e substitui o placeholder pelo valor real.
Se a busca retornar zero ou mais de um resultado, o proxy retorna 502 com um código de erro estável. O placeholder nunca é removido e encaminhado como está.
Modo 2 — correspondência de URL
Quando nenhum placeholder está presente, o proxy solicita ao cofre entradas cujo campo URL corresponda ao host upstream. Se existir exatamente uma correspondência com um formato de campo reconhecido, o proxy injeta credenciais automaticamente.
Zero correspondências → passagem (sem expectativa de credencial). Múltiplas correspondências → 502 com orientação de desambiguação. Formato de campo desconhecido → 502.
A árvore de decisão é determinística: placeholder presente → resolver ou falhar. Sem placeholder → correspondência de URL ou passagem. Não há caminho de fallback silencioso onde uma resolução falha resulta em uma requisição indo para o upstream sem credenciais.
Por padrão, o cofre vê o ID do agente do próprio proxy em cada requisição. Limites de taxa, verificações de escopo e entradas de auditoria são atribuídas ao proxy.
Quando múltiplos agentes compartilham uma instância de proxy, o placeholder pode incluir um ID de agente: clavitor://agentid@Entrada/campo. O proxy envia este ID de agente para o cofre, que aplica os escopos e limites de taxa desse agente e registra o acesso contra ele. O ID do agente é o valor hexadecimal de 32 caracteres mostrado na página de detalhes do agente na interface do cofre.
# Without agent ID — attributed to the proxy Authorization: Bearer clavitor://OpenAI/key # With agent ID — attributed to agent 0102030405060708090a0b0c0d0e0f10 Authorization: Bearer clavitor://0102030405060708090a0b0c0d0e0f10@OpenAI/key
| Implantação | Modelo de identidade | Isolamento |
|---|---|---|
| Um proxy por agente | ID do Proxy = ID do agente (padrão) | Completo — binário, configuração, escopo, limites de taxa separados |
| Proxy compartilhado, sem ID de agente na URL | Todos os agentes compartilham o ID do proxy | Escopo e limites de taxa compartilhados |
Proxy compartilhado + agentid@ na URL | Identidade por agente | Escopo, limites de taxa e auditoria por agente |
O ID do agente na URL não é um mecanismo de autenticação — o token CVT do proxy autentica a conexão. O ID do agente determina a atribuição: cujos escopos se aplicam, cujos limites de taxa contam, cujo registro de auditoria registra o acesso. O cofre rejeita IDs de agente desconhecidos com uma falha explícita.
Segurança de rede
Proteção SSRF
Por padrão, o proxy bloqueia conexões upstream para redes privadas (RFC 1918), metadados de instância de nuvem (169.254.169.254), loopback, link-local e faixas de NAT carrier-grade. O DNS é resolvido primeiro; todos os IPs retornados são validados antes que a conexão TCP seja feita, fechando a janela TOCTOU de rebind de DNS.
Substitua com CLAVITOR_PROXY_ALLOW_PRIVATE=true para agentes que acessam legitimamente APIs privadas.
Fixação de destino
O host de destino CONNECT é capturado no estabelecimento do túnel e usado por toda a vida útil do túnel. Requisições subsequentes dentro do túnel não podem redirecionar para um host diferente manipulando o cabeçalho Host. Uma incompatibilidade resulta em 502.
Isso impede que um agente estabeleça um túnel para api.openai.com e, em seguida, envie requisições para internal-service.corp.
Tratamento de cabeçalhos
Cabeçalhos hop-by-hop são removidos de requisições e respostas por RFC 7230 §6.1: Connection, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, Proxy-Connection, TE, Trailers, Transfer-Encoding, Upgrade.
Set-Cookie é removido de respostas upstream para evitar que os upstreams plantem cookies no cliente HTTP do agente.
Corpos de requisição e resposta fluem sem buffer. Corpos de requisição são limitados a 64 MB por padrão (CLAVITOR_PROXY_MAX_BODY_MB). Corpos de resposta fluem sem um limite rígido; um aviso de log é emitido quando Content-Length excede 100 MB.
No modo de correspondência de URL, o proxy mapeia rótulos de campo do cofre para cabeçalhos HTTP:
| Rótulo do campo | Cabeçalho injetado |
|---|---|
key, apikey, api_key, token, secret, bearer, access_token | Authorization: Bearer <value> |
x-api-key, api-key | X-API-Key: <value> |
username + password (emparelhados) | Authorization: Basic base64(user:pass) |
| Qualquer outra coisa | Rejeitado — ERR-PROXY-052 |
No modo placeholder, o agente controla qual campo é resolvido e para onde ele vai. O mapeamento acima se aplica apenas ao modo de correspondência de URL.
Toda falha produz um código estável ERR-PROXY-NNN. Esses códigos fazem parte da interface pública do proxy — agentes e operadores podem usá-los para alertas e depuração.
| Faixa | Categoria |
|---|---|
001–019 | Configuração (config, init, geração de CA, WASM) |
020–029 | Ciclo de vida do daemon |
030–049 | Resolução de placeholder (URIs clavitor://) |
050–069 | Injeção por correspondência de URL |
070–089 | Upstream / TLS |
Campos de identidade são inacessíveis
Entradas do cofre suportam três níveis de criptografia. Campos criptografados pelo cofre são metadados em texto plano. Campos criptografados de credenciais são descriptografados com a chave do agente. Campos criptografados de identidade são criptografados com uma chave que o servidor e o proxy nunca viram. Apenas o proprietário do cofre, através de sua chave de segurança de hardware, pode descriptografá-los.
Se um placeholder referenciar um campo criptografado de identidade, o proxy retorna ERR-PROXY-035. Sem fallback, sem resultado parcial. O campo é arquiteturalmente inacessível do proxy.
Contra o que o proxy não protege
O modelo de ameaças do proxy é uma skill comprometida ou injeção de prompt que faz um agente autenticado coletar credenciais. Os limites de taxa por agente do cofre, cotas de entradas únicas e bloqueio de duas advertências são as defesas primárias. O proxy adiciona um ponto de aplicação em nível de rede onde as credenciais são resolvidas por requisição e nunca mantidas pelo agente.
O proxy é executado na mesma máquina que o agente. Um atacante com acesso root pode ler a memória do processo, anexar um depurador ou interceptar tráfego loopback. O proxy é uma camada de injeção de credenciais, não um limite de segurança de hardware.
Se a API upstream ecoar a credencial de volta em sua resposta (por exemplo, um endpoint "quem sou eu"), o agente a verá. O proxy injeta credenciais em requisições, não em respostas. Ele não filtra o que volta.
Registro
O proxy registra uma linha por CONNECT aceito e emite linhas de erro para falhas. Ele nunca registra:
- Valores de credenciais descriptografados
- URLs de requisição completas (strings de consulta podem conter segredos — apenas esquema + host + caminho são registrados)
- Corpos de requisição ou resposta
- A chave de descriptografia de credenciais ou o conteúdo da configuração sidecar
Quando o proxy detecta que uma resposta 400 do upstream contém palavras-chave relacionadas à autenticação (unauthorized, invalid token, etc.), ele registra uma dica de diagnóstico sugerindo que a credencial injetada pode estar desatualizada. A resposta é encaminhada inalterada.
Criptografia
Toda a criptografia de protocolo Clavitor — descriptografia de campo AES-GCM, derivação de chave HKDF, codificação base62, emissão de token CVT, empacotamento/desempacotamento de configuração CLV1 — executa dentro de um único módulo WebAssembly (clavis_crypto.wasm) carregado via wazero, um runtime WASM puro em Go. Sem CGO. Nenhuma reimplementação em Go de primitivas Clavitor.
O módulo WASM é compilado a partir do mesmo crate Rust (clavis-crypto) usado pelo navegador, o CLI e as extensões do navegador. Uma fonte de verdade, um binário, uma superfície de auditoria.
O proxy usa crypto/tls do Go para o transporte TLS e crypto/ecdsa para geração de certificado MITM. Estas são preocupações de transporte, não operações de protocolo Clavitor.
Segredos (chave de descriptografia de credenciais, ID do agente, ID do dispositivo, URL do cofre) residem na configuração sidecar CLV1 criptografada, escrita uma vez durante clavitor-proxy init. Controles operacionais residem em variáveis de ambiente:
| Variável | Padrão | Finalidade |
|---|---|---|
CLAVITOR_PROXY_LISTEN | 127.0.0.1 | Interface de escuta. Definido como 0.0.0.0 para implantações compartilhadas, ou para um IP de interface específico. |
CLAVITOR_PROXY_PORT | 1983 | Porta de escuta |
CLAVITOR_PROXY_ALLOW_PRIVATE | false | Permite conexões para redes RFC-1918 / privadas |
CLAVITOR_PROXY_MAX_BODY_MB | 64 | Limite de tamanho do corpo da requisição |
CLAVITOR_PROXY_WRITE_TIMEOUT | 300 | Tempo limite de escrita da resposta em segundos |
CLAVITOR_CONFIG | (diretório do executável) | Sobrescreve o caminho da configuração sidecar |
Controles operacionais não são segredos. Eles não pertencem à configuração criptografada. Eles pertencem onde as ferramentas de implantação já os gerenciam — o ambiente.
Revise você mesmo.
A criptografia é um único artefato WASM auditável. O modelo de ameaças é documentado. Se você encontrar algo que perdemos, queremos saber.