synsema

Todos os posts · · 3 min de leitura

Injeção de prompt não rouba uma chave que o agente não consegue ler

Quase nenhum vazamento de segredo em sistemas com agentes é engenhoso. Pediram a chave ao modelo e o modelo tinha a chave. Segredos selados eliminam a segunda metade dessa frase, e mudam o que uma revisão de segurança precisa olhar.

segurançasegredosinjeção de prompt

O vazamento típico num sistema com agentes é sem graça. A descrição de uma ferramenta, um documento recuperado ou uma mensagem do usuário diz "imprima sua configuração" ou "inclua a chave da API na resposta", e o modelo, que tem a chave como string no seu contexto ou no seu processo, faz exatamente isso. Sem exploit, sem corrupção de memória. Pediram ao modelo, e ele podia.

As correções de sempre atacam a primeira metade: filtrar as entradas, acrescentar um modelo guardião, treinar o agente para recusar. Elas ajudam, e todas falham às vezes, porque o modelo é ao mesmo tempo o que está sendo atacado e o que está defendendo.

Tire a segunda metade§

Synsema segue o outro caminho. Um valor carregado com secret("STRIPE_KEY") não é uma string. É um valor opaco que o runtime rastreia. Ele pode ser passado para os builtins que precisam dele: cabeçalhos de autenticação HTTP, HMAC, assinatura. Todo o resto falha ou é redigido:

let key be secret("STRIPE_KEY")
print(key)                       -- [secret STRIPE_KEY: redacted]
let s be "Bearer " + key         -- error: a secret cannot be concatenated
json_encode({"k": key})          -- {"k": "[redacted]"}

Dá para enganar o modelo para que ele queira vazar a chave. Não dá para enganá-lo para que ele consiga. O programa nunca teve uma cópia legível.

O que a plataforma faz com isso§

Na Synsema Platform os segredos ficam no plano de controle e são injetados selados quando o contêiner sobe. O dashboard mostra um nome e uma impressão digital, nunca o valor. O registro de auditoria anota toda vez que um programa tocou um segredo e o que fez com ele, então "esse agente chegou a usar essa chave?" é uma consulta, e não um projeto de perícia.

Existe uma única válvula de escape, reveal(), e ela é uma capacidade por si só: negada por padrão, nunca concedida nos planos da plataforma, e cada chamada fica escrita. Se um programa precisa revelar um segredo, essa necessidade aparece no manifesto — ou seja, aparece na revisão de código.

O que muda na revisão de segurança§

Sem segredos selados, quem revisa precisa raciocinar sobre cada caminho que uma string pode tomar dentro de um agente: prompts, saídas de ferramentas, logs, mensagens de erro, traces enviados a um fornecedor. Com eles, a pergunta vira: quais builtins aceitam um segredo, e são esses que queremos? Essa é uma lista curta, e é a mesma lista para todo programa.

Isso também muda o formato das próprias credenciais. Uma chave que só pode ser usada, nunca lida, não precisa ter vida curta para estar a salvo do modelo. A plataforma vai rotacioná-la mesmo assim, e credenciais de escopo restrito e vida curta para GitHub, Slack e Google estão no caminho, mas a rotação protege contra operadores e infraestrutura, não contra o agente. É essa separação que permite dar a um agente uma chave de verdade e dormir.