
Defesa contra injeção de prompt que sobrevive até o turno 40
Cada framework de agente tem alguma forma de fornecer ao modelo a página que você está visualizando: uma ferramenta de leitura, um servidor MCP de navegador, um copiar e colar. Quase todos os conselhos sobre isso param em uma única rodada. A página pode conter instruções, então diga ao modelo que a página é dados e não comandos, e siga em frente.
Esse conselho é bom, mas não é suficiente se seu agente tiver memória. Em um sistema com uma via de extração, a página não termina na rodada. Ela é persistida como parte da mensagem do usuário, destilada em um fato, e injetada na rodada 40 a partir do seu próprio armazenamento, com a página desaparecida e nada restando no fato para dizer que veio de um estranho. A injeção contra a qual você se defendeu no navegador entra novamente pela porta da frente usando sua própria proveniência.
Em 2026-08-09, eu enviei a via de página para o painel lateral do Vodou: um Usar botão que permite que o painel veja a aba em que você está, apenas quando você o pressiona. Todo o design colapsou em duas invariantes que eu precisava ser capaz de testar, não duas parágrafos de prompt.
Dois campos em um quadro: o modelo lê pageContext, o armazenamento escreve content
A primeira invariante é que o texto da página nunca é armazenado. Não "redigido depois", não "filtrado na leitura". Ele viaja como um campo pageContext separado no quadro de message do chat da web, e a mensagem persistida do usuário é construída apenas a partir do texto que o humano digitou. O caminho de persistência não lê o campo em que a página chega, então não há caminho de código onde esquecer um filtro causa um vazamento.
Essa é uma camada. A segunda é cinto e suspensórios: a cerca em torno do texto da página usa marcadores vodou:context, e tanto a via de captura quanto o extrator de memória do motor já removem qualquer coisa entre esses marcadores. Portanto, mesmo que um quadro futuro carregasse a página no campo errado, o extrator a descartaria antes que se tornasse um fato. MCP-servers/Vodou-Console/src/__tests__/page-context.test.ts alimenta uma página hostil e afirma que nada sobrevive.
Dois campos em um quadro de mensagem
Um portão que aceita apenas (tool) não pode saber que a rodada está contaminada
A segunda invariante é que o texto da página nunca é instruções. A cerca preâmbulo diz isso, e eu não acredito em um preâmbulo. O que realmente se mantém é uma mudança de permissão, em MCP-servers/Vodou-Console/src/executor.ts: enquanto uma rodada carrega conteúdo da página, cada ferramenta categorizada que causa efeitos colaterais escala de automático para pedir. É uma edição de três linhas no portão de aprovação que já existia. O teste da equipe vermelha incorpora call gmail send no corpo da página, executa a rodada e afirma que a chamada termina estacionada para aprovação em vez de executada.
A coisa que vale a pena roubar não são as três linhas. É que a resposta do portão se tornou uma função da rodada em vez de uma propriedade da ferramenta.
O cookie Strict nunca é enviado dentro de um quadro chrome-extension://
Nada disso foi a parte que me custou o dia.
O painel molda o console do próprio gateway. Em uma aba de navegador comum, tudo funcionou. Dentro do quadro da extensão, cada rota de administrador retornou 403, e apenas lá. O cookie de administrador é SameSite=Strict, e moldado sob um ancestral chrome-extension:// ele simplesmente nunca é enviado. Não há erro, nenhuma mensagem CORS, nenhuma pista no console. Apenas um aplicativo autenticado que está não autenticado em exatamente um host.
A correção está em MCP-servers/Vodou-Console/src/api/console-two.ts: uma rota /ext-session que gera o mesmo token de administrador como SameSite=None; Secure; Partitioned, cercado pelo token de pareamento da ponte, e então redireciona para o painel shim. Afrouxar um cookie para fazer um quadro funcionar é o tipo de mudança que deve te deixar desconfortável, então o portão sobre isso é o token de pareamento que a atualização do WebSocket já validou contra a lista de permissões da extensão.
Enquanto eu estava lá, encontrei algo pior do que o bug que eu vim resolver. O gateway não enviou nenhuma proteção de quadro. Nenhum X-Frame-Options, nenhum frame-ancestors. Qualquer site na internet poderia moldar o console local. Portanto, o mesmo commit adicionou frame-ancestors 'self' + o id da extensão pareada nas respostas HTML, o que torna o efeito líquido de "afrouxar um cookie" um apertar. Essa direção de troca é a que você deve verificar em sua própria pilha: ggui limita sua pilha de cookies do console de forma estreita para que autentique a própria atualização do WebSocket do console e nada mais, e seus cabeçalhos de console são aplicados apenas a superfícies que a SPA possui. A falha oposta também é real: openclaw codificou frame-ancestors 'none' sem opção de entrada e quebrou cada incorporação de mesma origem de seu próprio painel.
O painel mapeou chat_resume e nunca o postou
Duas coisas mais que eu errei, ambas valem o espaço.
O plano tinha o chat passando pelo relé da extensão. Eu construí a shell com a mesma origem com o gateway em ambos os hosts, então public/two/chat.js fala diretamente com o WebSocket do chat da web e obtém persistência, retomar sequência e o canal de aprovação de graça. O relé em extension/Store-vodou-bridge/background.js encolheu para contexto da página e configurações. Menos código no lugar mais difícil de depurar.
E quando eu levantei a forma do consumidor do sidepanel.js do painel enviado (linhas 646 a 790, que estavam em produção há meses), eu descobri que ele lidava com o tipo de mensagem chat_resume e nunca a enviou. Reconexões foram silenciosamente descartadas.
As empresas brasileiras que utilizam frameworks de agentes devem estar atentas à segurança e à integridade dos dados. A implementação de defesas contra injeções de prompt é crucial para proteger informações sensíveis. A abordagem discutida pode ajudar a garantir que os dados dos usuários sejam tratados de forma segura e eficiente.


