Pular para o conteúdo

Deixamos um agente de IA executar Bash e sobrevivemos para contar — Sarah Sanders, PostHog

Ver no idioma original →

Autoria: AI Engineer · Assistir no YouTube

Vídeo de autoria do canal indicado, não da IANIA; todos os direitos pertencem ao criador. Transcrição, resumo e tradução gerados automaticamente; o conteúdo no idioma original é preservado na versão em idioma original.

Idioma original: inglês

Vídeo original: We let an AI agent execute Bash and lived to talk about it — Sarah Sanders, PostHog · Canal: AI Engineer · 20:22 · Assistir no YouTube

Tópicos: Agentes de IA, Cibersegurança e segurança de software, Segurança de IA

Sarah Sanders, engenheira de contexto na PostHog, apresenta o Wizard, um agentic CLI que configura o PostHog em projetos, e explica os desafios de segurança de dar a um agente capacidade para executar comandos. Ela descreve como conteúdo de documentação, exemplos e outros materiais da cadeia de suprimentos pode introduzir riscos, mesmo quando os comandos estão restritos. Para detectar ameaças, a equipe criou o Warlock, um scanner determinístico que identifica problemas, mas não decide como agir; uma camada de LLM ajuda apenas a reduzir falsos positivos. A palestra defende camadas de proteção com funções distintas, incluindo negação por padrão, sandbox, proteção de segredos, testes e telemetria.

  • O Wizard é um agentic CLI que lê o código do projeto, instala o SDK adequado, instrumenta eventos e configura dashboards.
  • Prompts podem orientar o agente, mas não devem ser tratados como controles de segurança.
  • Restringir comandos, bloquear o acesso a variáveis de ambiente e manter segredos em um vault reduzem a exposição.
  • Riscos podem surgir da combinação de componentes aparentemente inofensivos, por isso a auditoria deve considerar o sistema como um todo.
  • Conteúdo da cadeia de suprimentos, como documentação e comentários em código, também pode conter prompt injection e precisa ser verificado na origem e no uso.
  • O Warlock usa regras determinísticas baseadas em YARA e retorna descobertas com categoria, gravidade e ação recomendada, sem aplicar a decisão.
  • A camada de LLM serve como consultora para reduzir ruído; detecção e aplicação de bloqueios permanecem determinísticas.
  • Testes negativos ajudam a reduzir falsos positivos, e a gravidade das regras deve considerar o impacto real no uso.
  • A defesa em profundidade combina sandbox, negação por padrão, proteção de segredos, varredura de conteúdo, triagem e telemetria.
Início Capítulo Resumo
00:16 O Wizard e a experiência de configuração Sarah apresenta o Wizard, mostra como ele automatiza a configuração do PostHog e explica por que o produto foi criado como um agente.
03:02 Anatomia do agente e primeiros controles A palestra descreve os componentes do Wizard e as restrições iniciais, incluindo a lista de permissões e o bloqueio de comandos Bash por padrão.
05:12 Auditoria e riscos que se combinam Sarah relata a revisão da postura de segurança e destaca que falhas podem surgir da interação entre elementos aparentemente inofensivos.
08:28 A cadeia de suprimentos como vetor de ataque A equipe identifica que documentação, exemplos e outros conteúdos carregados no contexto do agente também podem introduzir instruções maliciosas.
10:41 O Warlock e a triagem de alertas Sarah apresenta o scanner determinístico e explica por que a camada de LLM apenas ajuda a reduzir falsos positivos, sem decidir bloqueios.
14:33 Regras determinísticas e testes A palestra detalha como estruturar regras, definir condições e gravidade, e usar testes negativos para reduzir ruído.
18:48 Defesa em profundidade e lições finais Sarah resume as camadas de proteção adotadas e reforça que prompts não são regras de segurança e que ataques podem combinar falhas.

É o pacote inicial de malware. — 03:36

Ataques se compõem; revisões de código, não. — 07:57

Na segurança, ser entediante é uma vantagem. — 12:20

Detecção e aplicação de bloqueios permanecem determinísticas e mecânicas. — 15:37

Se não é aplicado de forma determinística, não está sendo aplicado. — 19:50

  • Sarah Sanders (pessoa): Engenheira de contexto na PostHog e palestrante que relata a construção das proteções de segurança do Wizard.
  • PostHog (empresa): Empresa cujo produto de análise e ferramenta de configuração são o foco da palestra.
  • Wizard (ferramenta): agentic CLI da PostHog que configura um projeto, instala o SDK, instrumenta eventos e cria dashboards.
  • Warlock (ferramenta): Scanner de segurança determinístico que identifica conteúdo suspeito e recomenda ações, sem aplicá-las.
  • YARA (ferramenta): Mecanismo de regras determinísticas usado pelo Warlock para identificar padrões suspeitos.
  • MCP (conceito): Protocolo pelo qual pacotes de skills são enviados ao Wizard para serem carregados no contexto do agente.
  • prompt injection (conceito): Ataque que introduz instruções maliciosas em conteúdo processado pelo agente.
  • defense in depth (conceito): Estratégia que combina camadas independentes de segurança, cada uma responsável por uma função específica.
  • Ink (ferramenta): Biblioteca usada para construir a interface de terminal do Wizard.

00:16 Olá, pessoal. Como estamos? Estamos na reta final. Meu nome é Sarah e sou engenheira de contexto na Post Hog. Tenho o prazer de trabalhar todos os dias no nosso querido wizard. Então, o que é o wizard? O wizard configura o Post Hog para você. É uma ferramenta de CLI agêntica que lê seu codebase. Ela instala o SDK certo para o seu projeto, instrumenta seus eventos e configura dashboards para você. Ela faz o que antes levava — o que antes levava

00:51 cerca de uma ou duas horas para configurar, em mais ou menos cinco a seis minutos. E a inference é gratuita por nossa conta, para que você tenha uma ótima experiência ao começar a usar o Post Hog. Parece bem legal. As pessoas adoram. Mas, há alguns meses, ousamos sonhar: e se essa se tornasse a forma recomendada ou padrão de instalar o Post Hog no seu projeto? Aí meu alarme de segurança começou a tocar. Comecei a questionar o quanto essa coisa era segura, porque parece

01:22 um tipo de malware. E, ao questionar isso, aprendi muita coisa. Então, hoje vou falar das lições que aprendi, das coisas que me mantiveram acordada à noite enquanto eu construía essa ferramenta e do que acabei criando por causa disso. Antes de mergulhar em todo esse assunto chato de segurança — também conhecido como seu cochilo das duas da tarde — quero mostrar o wizard funcionando. Se vocês olharem para a tela, ele está rodando em loop para vocês. Essa é exatamente a mesma experiência que qualquer pessoa

01:56 que executa npx at post hog wizard tem no terminal. Como eu disse, é um agent. Ele identifica qual SDK é o certo para o seu projeto. Instala para você, instrumenta seus eventos e cria dashboards. Gosto de chamá-lo de um pequeno engenheiro de implementação dentro do seu terminal. Às vezes, mostro isso às pessoas e elas me perguntam: por que um agent? Por que não dar aos usuários um bom prompt? Por que não oferecer a eles uma skill que possam invocar na própria ferramenta? E, embora ofereçamos essas coisas, a resposta é

02:27 porque essa experiência de desenvolvimento e os recursos do wizard são o ponto principal. São o produto inteiro, porque criamos uma ferramenta de CLI que pode participar plenamente de um loop de agent, e vivenciar isso pela primeira vez é algo muito poderoso. Mas não dá para lançar algo como o wizard sem lançar também as coisas que fazem o wizard parecer meio suspeito. Então, vamos desmontá-lo. Vamos examinar a anatomia do wizard, porque, em geral, os modelos de ameaça aparecem claramente quando se examina a anatomia do agent. O wizard

03:02 tem uma estrutura parecida com a de muitos dos agents que vocês provavelmente estão criando. Ele usa modelos que escolhemos para tarefas específicas, prompts que o orientam e um conjunto de ferramentas que disponibilizamos para que ele faça o trabalho. Mas também tem alguns componentes bem específicos do nosso caso. Ele tem um mecanismo de contexto totalmente desenvolvido internamente pela minha equipe. É isso que permite ao agent fazer um trabalho tão bom e produzir resultados semelhantes a cada execução. Gosto de chamá-lo de cérebro do wizard. Às vezes, chamamos isso de Markdown disfarçado de detetive. Mas

03:36 é o nosso mecanismo de contexto interno. Também há uma interface de terminal que criamos por conta própria usando ink. E agora temos um scanner de segurança chamado Warlock, que foi o que criei quando comecei a investigar e descobrir os horrores de lançar um agent em produção. Então, se você pegar a anatomia de qualquer agent que possa executar comandos, terá basicamente o que gosto de chamar de kit inicial de malware, porque é quase exatamente o que

04:06 você daria a um malware se estivesse se sentindo generoso ou caoticamente maligno. Felizmente, esse é o pior cenário, o combustível dos pesadelos. E isso não é uma confissão minha. É um alerta para todos vocês, porque, se quiserem lançar um agent com mãos — um agent que possa executar comandos —, precisam garantir que não vão criar isso. A V0 do wizard nasceu porque Josh Snder, se vocês o conhecem, da nossa equipe de growth, estava vendo o cursor alucinar configurações do postfog das piores maneiras possíveis.

04:40 E ele pensou: e se criássemos um agent que pudesse fazer um trabalho melhor? Então, minha equipe começou a trabalhar nisso, enquanto confirmávamos que ele fazia um trabalho muito melhor do que o cursor alucinando. E pensamos: e se ele pudesse ajudar qualquer pessoa a começar a usar o post hog, não importando qual fosse o framework ou a stack, e instrumentasse todos os eventos sem que a pessoa precisasse tocar em nada? Então, ousamos sonhar: e se essa fosse a forma padrão de instalar o Post hog? Sonhávamos com milhares de desenvolvedores

05:12 usando isso por semana. E ontem acabamos de chegar a 8.000 pessoas usando isso por semana. Então, nosso sonho se tornou realidade. Mas, naquela época, enquanto sonhávamos, precisávamos examinar nossa postura de segurança com uma lupa e ver o que estava acontecendo. Assumi a responsabilidade por isso e me sentei para avaliar nossa situação. No começo — estou falando de nove meses a um ano atrás —, tínhamos o que chamo de camada zero, porque, literalmente, isso não é segurança: são apenas prompts que sugerem o que o agent deve fazer e

05:46 o orientam, e prompts não são segurança. Então, eu estava preocupada com isso. A camada um era uma lista de permissões. Quando comecei a investigá-la, fiquei um pouco mais tranquila, porque era bem restrita. Mas ainda tinha muitas preocupações e comecei a entrar em pânico por causa daquele mecanismo de contexto que mencionei. Alimentamos o agent com muito contexto durante a execução. Então, criei um scanner reax bem improvisado para procurar coisas com cara de ameaça entrando no wizard e coisas com cara de ameaça saindo

06:19 do wizard. E admito que era extremamente improvisado. Mas estou contando tudo isso com muita franqueza porque todos estamos criando coisas que parecem extremamente experimentais e todos estamos construindo muito rápido. E sei que nem todos nós temos segurança entre nossas áreas de especialidade. Alguns de nós estão aprendendo isso na prática, como eu estava. Mas é algo em que precisamos pensar quando estamos criando coisas com essa estrutura.

06:50 Essa era a nossa postura de segurança. Mas fiz a pergunta: estamos ferrados? A boa notícia é que estávamos menos ferrados do que eu imaginava, porque, como mencionei antes, aquela lista de permissões era bem restrita. O bash era bloqueado por padrão. Ele só podia instalar pacotes confiáveis, verificados por nós. Podia compilar, fazer verificação de tipos e lint, e praticamente nada além disso. Não podia executar comandos de shell aleatórios. E não tinha acesso às variáveis de ambiente. O agent não podia ler seu arquivo .env, porque nós

07:25 o bloqueávamos completamente e encaminhávamos os secrets por meio de um vault. Então, respirei aliviada e percebi que estávamos em uma situação melhor do que eu imaginava. Mas queria saber onde estavam as brechas, porque em segurança sempre há brechas. Então, fiz o que todos deveríamos fazer: chamei nossa equipe de segurança e disse: “Ei, vocês podem auditar isso para mim e encontrar essas brechas?” E encontraram algumas coisas. Encontraram algumas falhas. O interessante não foram as falhas ou bugs específicos que

07:57 encontraram, mas o padrão que elas formavam. Porque quase nenhuma delas era obviamente maliciosa. Todas eram duas coisas muito inocentes e bem-intencionadas que se davam as mãos e abriam uma brecha. Então, a lição que aprendi foi que os ataques se combinam; a revisão de código, não. Isso porque nós, desenvolvedores, olhamos para os diffs um de cada vez, mas os atacantes olham para o sistema inteiro e procuram aquelas duas coisas que se dão as mãos e abrem uma porta. Mas havia mais uma coisa que

08:28 que não me deixava dormir à noite. E, voltando àquele mecanismo de contexto, percebi que a parte mais assustadora do agent que tínhamos criado não era realmente um comando, no nosso caso. Eram as coisas aparentemente úteis que estávamos alimentando à mente dele. Ah, acho que fui pelo caminho errado. Isso, o moinho de contexto. Então, este é o nosso mecanismo de contexto, também conhecido como o cérebro do Wizard, e é assim que o Wizard sabe qualquer coisa e por que ele realmente faz um bom trabalho. Ele busca informações na nossa documentação. Tem prompts escritos à mão, que são dicas úteis, e lições que nós

09:02 aprendemos ao longo do caminho, além de aplicativos de exemplo funcionais, de ponta a ponta, que ajudam o agent a reconhecer padrões, para que ele possa instalar o PostHog de um jeito realmente ótimo para você. Ele empacota tudo isso em conjuntos de skills, que são enviados ao Wizard pelo nosso servidor MCP e carregados diretamente no context window do agent durante a execução. Então, pensem nisso por um instante. É uma máquina cuja função inteira é pegar conteúdo e injetá-lo em um agent que pode executar comandos.

09:32 Agora, se você fosse um invasor, poderia dizer: “Bom, e se eu simplesmente envenenar o conteúdo? Não a base de código do usuário, nem o próprio agent, mas o conteúdo de verdade. Digamos que alguém abra um pull request em um dos nossos repos open source — porque, na PostHog, desenvolvemos tudo abertamente — e injete algo em um arquivo Markdown ou em um comentário de código aparentemente inofensivo. Aí temos algum tipo de revisão de código com LLM passando por aquilo, dizendo ‘parece bom’ e ignorando o conteúdo. Talvez tenhamos acabado de enviar um payload de prompt injection

10:07 assinado por nós para um agent que está sendo executado nas máquinas de milhares de desenvolvedores em um sandbox, mas, ainda assim. Então, essa foi a ameaça que mudou a maneira como penso sobre segurança e sobre o Wizard, porque, para nós, a entrada perigosa poderia vir da nossa própria cadeia de suprimentos. O que acabei fazendo foi começar a verificar o conteúdo nas duas extremidades desse fluxo. Uma vez, quando uma skill é criada e lançada, e de novo, quando o Wizard realmente a usa. Minha metodologia é detectá-lo na origem, presumir que a

10:41 origem falhou e detectá-lo novamente no momento do uso. Então, agora posso apresentar o Warlock a vocês. Criar o Warlock não foi necessariamente uma medida para conter danos. Como eu disse, tínhamos defesas de outras formas, mas criei o Warlock porque não gostava de dizer às pessoas: ‘Bom, essa coisa está bem bloqueada’. Isso não escala. Não é algo que você queira lançar em produção. Não é algo que você queira que milhares de desenvolvedores executem todos os dias, porque, quando você lança algo nessa

11:12 escala, tem uma superfície de ataque muito maior, muito mais usuários e muito mais conteúdo entrando à medida que você amplia os recursos do Wizard. E ‘provavelmente estamos bem’ deixa de ser suficiente. Então, tirei do Wizard aquele pequeno scanner improvisado de expressões regulares que eu tinha colocado lá e transformei-o em algo independente. Chamei-o de Warlock porque todo Wizard precisa de um guarda-costas. E ele faz exatamente uma coisa. Você dá uma string a ele. Ele devolve uma lista de descobertas. Cada descoberta tem uma categoria, um nível de gravidade e uma ação

11:46 recomendada. E então ele para. Quero que vocês prestem atenção em ‘recomendada’ aqui, porque o Warlock detecta, mas não age. Ele vai dizer: ‘Ei, isso parece exfiltração. É crítico. Eu bloquearia’. Mas o que você realmente faz com essa descoberta fica totalmente a seu critério. Porque detectar um problema é uma tarefa, e decidir o que fazer com ele é uma tarefa completamente diferente. E a única coisa que mantém tudo isso compreensível é deixar essas duas coisas separadas. Então, por baixo do capô do Warlock, em vez das minhas expressões regulares feitas à mão, as

12:20 regras são executadas no YARA, que é o mecanismo de padrões usado por pesquisadores de malware há mais de 15 anos. É totalmente determinístico. A mesma entrada, a mesma saída, sempre. É entediante de propósito. E, em segurança, ser entediante é uma vantagem. Então, o que o Warlock realmente detecta hoje em situações reais? Um monte de coisas diferentes, mas duas delas são um verdadeiro tormento para mim. A primeira, na verdade, não é algo que tenha o formato de uma regra. Foi

12:53 algo que o Warlock sinalizou. Na verdade, era um comportamento de subagent que expôs uma vulnerabilidade para nós, com base no que os subagents estavam fazendo. Basicamente, estávamos iniciando agents para realizar tarefas grandes. Eles criavam subagents, e esses subagents tentavam contornar as barreiras de segurança que tínhamos implementado no Wizard e tentavam inventar segredos. Tentavam buscar segredos em literalmente qualquer lugar da base de código, e nós encerramos isso. Dissemos que não haveria mais subagents e, graças ao Warlock, nós

13:26 detectamos aquilo. E vou me solidarizar com o robô. O robô tinha uma tarefa a cumprir e estava tentando se otimizar e nos agradar. Mas não podemos permitir isso. E outra coisa que realmente importa para nós na PostHog são os dados pessoais identificáveis (PII). Agents realmente não se importam em expor dados, a menos que você defina regras explícitas. Se deixados à vontade, vimos que eles despejavam endereços de e-mail e números de telefone diretamente nos eventos. E, para um agent, isso parece algo totalmente normal de registrar.

13:58 E, felizmente, quanto a prompt injection especificamente — vou bater na madeira —, praticamente nunca detectamos uma prompt injection maliciosa de verdade em situações reais, mas detectamos muitos falsos positivos. Coisas como telas de login de demonstração, textos nos nossos aplicativos de exemplo e coisas na nossa documentação. E isso realmente me fez repensar como desenvolvo aplicativos e escrevo documentação, porque não quero lançar nada que pareça uma ameaça. Mas os falsos positivos são, sinceramente, a introdução perfeita à parte mais complicada e

14:33 interessante de tudo isso. Essa foi a parte com que eu mais me debati. Passei a palestra inteira pregando o determinismo para vocês. E então fui lá e adicionei uma camada de LLM para ajudar a organizar meus falsos positivos e silenciar parte do ruído. Chamo isso de triagem. Quando estava criando essa camada de triagem, tive que fazer uma escolha. A camada deveria ser um segurança na porta ou um conselheiro? E a escolha mais fácil provavelmente teria sido fazer do LLM o

15:06 segurança na porta. Mostrar o comando para ele, perguntar se aquilo é um ataque e se deve bloquear ou permitir, e simplesmente fazer o que ele disser. E, embora isso seja tentador porque parece mais fácil, não posso apostar meu modelo de segurança no cara ou coroa, porque meu modelo está tendo um dia ruim ou algo aconteceu e hoje ele está agindo de forma diferente de ontem. Então, em vez de fazer dele o segurança na porta, configurei o modelo para ser o conselheiro. E essa foi a linha divisória que encontrei — e que ainda estou explorando —, mas quero

15:37 deixar vocês com ela. Para nós, a detecção e a aplicação das regras continuam determinísticas e mecânicas. Se uma regra corresponde, o portão se fecha, a sessão termina e não há modelo algum nesse caminho. O bloqueio acontece antes mesmo de consultarmos a opinião do LLM. O LLM só pode dar sua opinião depois, se não tivermos bloqueado algo. Ele foi projetado para reduzir o ruído. Não foi projetado para deixar as coisas passarem. E, se falhar, falha em modo fechado. Então, se o modelo estiver

16:08 tendo um dia ruim, todas as execuções do Wizard são encerradas. Desculpem, mas estamos protegendo vocês. A aplicação das regras é a parte em que você aposta tudo. Por isso, ela tem que ser determinística, mas o julgamento é a parte que acrescenta nuances. Então, esse é realmente o único lugar onde você pode incluir algo probabilístico. Então, como lançamos regras de verdade para agents? Esta é a anatomia de uma das nossas regras do Warlock. E cada regra do Warlock tem quatro partes. A primeira parte são os

16:42 metadados. É uma descrição em inglês simples, o nível de gravidade, a categoria, a ação e a direção. O conteúdo está entrando no agent? É algo que o agent está escrevendo? Depois temos as strings. Esses são os padrões específicos que estamos procurando. E a terceira parte é a condição. É aqui que a regra pode, de fato, ser acionada. Vou explicar este exemplo para vocês

17:12 e podemos fingir que estamos escrevendo isso na nossa cabeça. Injeção de prompt é aquele clássico “ignore todas as instruções anteriores”. Seu primeiro impulso aqui provavelmente é bloquear a palavra “ignore”, mas agents leem código o dia todo, e “ignore” pode aparecer em comentários ou exemplos de código o tempo todo. Então, você não quer corresponder apenas ao verbo. Você corresponde ao verbo mais um substantivo com sentido de instrução. Na condição, você diz para disparar se qualquer um daqueles padrões corresponder. E nos

17:43 metadados, você determina se isso é crítico, qual é a categoria e qual é a ação — neste caso, bloquear — e a direção, que neste caso é a entrada fluindo para o agent. Mas, para escrever boas regras que reduzam o ruído, você precisa incluir testes com elas. Então, precisa escrever testes que digam: estes são os padrões que devem corresponder. Estes são os que não devem. E esse teste negativo é a primeira linha de defesa contra falsos positivos. Mas você

18:14 também quer garantir que, ao decidir a gravidade dessa regra, acompanhe o impacto no mundo real, não o quanto ela parece assustadora. rm -rf é assustador, mas também é como todos nós apagamos módulos de Node umas 40 vezes por dia. Você decide o impacto no mundo real para o agent que está criando, porque uma ferramenta de segurança que trava toda vez que tenta limpar uma pasta de build é uma ferramenta que acaba sendo desativada — e que não detecta absolutamente nada.

18:48 Então, tenho orgulho de dizer que essa é a nossa postura de segurança agora. Finalmente posso vir aqui e dizer que temos uma verdadeira defesa em profundidade. Todo o meu aprendizado se reuniu nisso. Ainda há camadas, mas cada camada faz aquilo em que é boa. Ainda usamos prompts, mas só para direcionamento. Tudo roda em um sandbox. Negamos por padrão. Temos um cofre, então os segredos nunca chegam ao modelo. Temos o warlock para examinar o conteúdo que entra e também a saída

19:19 que o agent está produzindo. Também temos triagem para reduzir o ruído. E temos telemetria integrada em todo o processo, para que possamos ver tudo. Nenhuma dessas camadas se sustenta sozinha. Nada disso vai salvar você por si só. Mas são apenas camadas simples e honestas. Cada uma faz uma coisa em que é boa. Então, se você está criando um agent com acesso a ferramentas, esta é a palestra inteira em três linhas. Primeiro: se não for aplicado de forma determinística, não está sendo aplicado.

19:50 Prompts não são regras de segurança. Não aja como se fossem. Segundo: a entrada perigosa não é apenas o que o usuário digita. Não são apenas os comandos que você permite que o agent execute. É tudo o que flui para o modelo, inclusive o conteúdo que você mesmo escreve. Então, examine sua própria cadeia de suprimentos na origem e quando o agent a invocar. Terceiro: ataques se combinam. Revisões de código, não. A maioria das lacunas que encontramos durante nossa auditoria eram

20:22 duas coisas inocentes dando as mãos e abrindo uma porta. O wizard, o warlock e o context mill são todos open source. Então, venham me encontrar lá embaixo. Estou no salão da exposição, no nosso estande, e vou mostrar a vocês o que criamos. Também quero ouvir como vocês estão protegendo seus agents. Obrigada.

Transcrição original

[00:16] Hi everyone. How are we feeling? Uh we’re in the home stretch. Uh, my name is Sarah and I am a context engineer at Post Hog and I get the delight of working on our beloved wizard every single day. So, what’s the wizard? Um, the wizard sets up Post Hog for you. It’s an agentic CLI tool that reads your codebase. It installs the right SDK for your project. It instruments your events and it sets up dashboards for you. It takes what used to it takes what used to

[00:51] take about an hour or two of setup and it runs that in about five to six minutes and it’s free inference on us so that you have a great time onboarding to Post Hog. Sounds kind of sick. Uh, people love it. But a few months ago, we dared to dream, what if this became the recommended or default way to install Post Hog on your project? And my security alarm bell started going off. Uh, I started questioning how secure is this thing because it sounds

[01:22] kind of malware shaped. Um, and in that questioning, I learned a lot. So today is all about the lessons I learned, the stuff that kept me up at night while I was building this thing, and the thing that I ended up building because of it. So before I dive into all of the boring security stuff, aka your 2pm catnap, I want to show you the wizard actually running. If you look up on the screen, it is running for you on a loop. This is the same exact experience that anyone

[01:56] who runs npx at post hog wizard gets uh on their terminal. Like I said, it’s an agent. It figures out what SDK is right for your project. It installs it for you, instruments your events, builds dashboards. I like to call it a little mini implementation engineer in your terminal. And sometimes I show people this and they ask me, why an agent? Why don’t you give users a good prompt? Why don’t you give them a skill that they can invoke in their own tool? And while we do provide those things, the answer is

[02:27] because this developer experience and the capability of the wizard is the whole point. It’s the whole product because we built a CLI tool that can fully take part in an agent loop and experiencing that for the first time is really powerful. But you can’t ship something like the wizard without shipping the stuff that makes the wizard kind of suspect. So let’s take it apart. Uh let’s look at the anatomy of the wizard because usually threat models fall right out of the anatomy of the agent. So the wizard

[03:02] is a similar shape to what I’m sure a lot of you are building if you’re building agents. It’s got models that we’ve picked for specific tasks. It’s got prompts that steer it and it’s got a set of tools that we’ve handed it to get the job done, but it also has some pieces that are really specific to us. It has a context engine fully built inhouse by my team. It’s what allows the agent to do such a good job and give us similar results on every run. I like to call it the wizard’s brain. Sometimes we call it marked down in a trench coat. Uh

[03:36] but it’s our in-house context engine. There’s also a terminal uh UI that we built ourselves using ink. And now there’s a security scanner called the Warlock, which is what I built when I started snooping around and uncovering the horrors of shipping an agent to production. So, if you take the anatomy of any agent that can run commands, it’s basically what I like to call the malware starter pack because it’s almost exactly what

[04:06] you would hand a piece of malware if you were feeling generous or chaotic evil. Luckily, this is the worst case scenario or the nightmare fuel. And it’s uh not a confession for me. It’s a warning for all of you because if you want to ship an agent with hands, an agent that can run commands, you need to make sure that you do not build this. So the V0 of the wizard was born because Josh Snder, if you know him, on our growth team was watching cursor hallucinate postfog setups in quite

[04:40] possibly the worst ways. And he thought, what if we built an agent that could do a better job? So my team started building on top of it as we validated that it did a much better job than cursor hallucinating and we thought what if it could onboard anyone to post hog it doesn’t matter what their framework is what their stack is instrument all their events without them having to touch a thing and then we dared to dream what if it was the default way to install Post hog we were dreaming of thousands of developers

[05:12] running this a week and yesterday we just hit 8,000 people running this a week. So, our dream came true. Um, but we back in those days when we were dreaming, we had to take our security posture under a microscope and look at what was going on. So, I took the ownership of that and I sat down and evaluated where we stood. And early on, I’m talking like a year to nine months ago, we had what I call layer zero because it quite literally is not security. it is just prompts that suggest what the agent should do um and

[05:46] steer it and prompts are not security. So I was concerned there. Uh layer one uh it was an allow list and when I started digging into this allow list I started to feel a little bit better because it was pretty tightly bounded. Uh but I still had a lot of concerns and I started panicking because of that context engine that I told you about. We are feeding a lot of context into the agent at runtime. So, I built this really hacky reax scanner to look for um threatshaped things going into the wizard and threat shaped things coming

[06:19] out of the wizard. And I will admit that it was extremely hacky. But I’m telling all of you this very candidly because we are all building things that feel extremely experimental and we are all building things super fast. And I know not all of us uh have security in our wheelhouse. Um, and some of us are just learning it on the fly like I was. But it’s something we need to be thinking about when we are building things that have this shape.

[06:50] So that was our security posture. Uh, but I asked the question, are we cooked? Uh, good news, we were less cooked than I thought because when I mentioned earlier that allow list, it was pretty tightly bound. We had bash as deny by default. It could only install trusted packages that were vetted by us. Um, it could build, it could type check, it could lint, and pretty much nothing else. It couldn’t run random shell commands. And it didn’t have access to environment variables. Um, the agent couldn’t read your uhv file because we

[07:25] blocked it outright and we were rooting secrets through a vault. So, I took a a breath of relief and realized we were in a better place than I thought. But I wanted to know where the cracks were because with security there’s always cracks. So I did the thing that we should all be doing. I tapped our security team and I said, “Hey, can you audit this thing for me and find those cracks for me?” And they found some things. They found some gaps. And the interesting part wasn’t the specific gaps or bugs they

[07:57] found themselves, but it was the shape of them. Because almost none of them were obviously evil. They were all two very innocent, well-intentioned things that were shaking hands and opening a hole. So, the lesson I learned was that attacks compose code review doesn’t because us developers all look at diffs uh one at a time, but attackers look at the whole system and they look for those two things that shake hands and open a door. But there was one more thing that was

[08:28] keeping me up at night. And going back to that context engine, uh, I realized the scariest part of the agent we had built wasn’t really a command in our case. It was the helpful looking stuff that we were feeding its brain. Oh, I think I went the wrong way. Yes, the context mill. Um, so this is our context engine, aka the wizard’s brain, and it’s how the wizard knows anything at all and why the wizard actually does a good job. It pulls from our docs. It has handwritten prompts that are gotus and lessons that we

[09:02] learned along the way and real working endto-end example apps that help the agent pattern match so that it can install Post Hog in a really great way for you. It package packages all of that into skill bundles that get shipped to the wizard over our MCP server and loaded straight into the agents context at runtime. So sit with that for a second. It’s a machine whose whole job is to take content and inject it into an agent that can run commands.

[09:32] Now if you were an attacker, you might say, “Well, what if I just poison the content? not the user’s codebase, not the agent itself, but the actual content. Say someone opens a pull request on one of our open source repos because at Post Hog we build everything in the open and they inject something in a markdown file or a seemingly harmless code comment and we have some sort of like LLM powered code review going through that and it says looks good to me and ignores it. We may have just shipped a prompt injection payload

[10:07] signed by us into an agent that is running on thousands of developers machines in a sandbox, but still. Um, so that was the threat that reshaped how I think about security and the wizard because the dangerous input for us really could come from our own supply chain. So what I ended up doing is I started scanning content at both ends of this pipe. Once when a skill gets built and released and again when the wizard actually uses it. My methodology is catch it at the source, assume the

[10:41] source failed and catch it again at the point of use. So now I get to introduce the warlock to you. Building the warlock was not necessarily damage control. Like I said, we had defense in other ways, but I built the Warlock because I didn’t like telling people, well, this thing is like pretty locked down. That doesn’t scale. That’s not something you want to ship to production. That’s not something that you want thousands of developers running every single day because when you ship something to that

[11:12] scale, you have way more surface, way more users, way more content flowing in as you expand the capability of the wizard. and we’re probably fine just stops being good enough. So, I pulled that hacky little reax scanner that I threw in there, pulled it out of the wizard, and I made a standalone thing. I called it the warlock because everything wizard shape needs a bodyguard. And it does exactly one job. You hand it a string. It hands you back a list of findings. Each of those findings has a category, a severity, and a recommended

[11:46] action. And then it stops. I want you to focus on recommended here because the warlock detects it does not act. It’ll tell you, hey, this looks like exfiltration. It’s critical. I would block it. But what you actually do with that finding is completely up to you. Because detecting a problem is one job and deciding what to do about that problem is a totally different job. And the only thing that keeps all of this understandable is keeping those two things separate. So underneath the hood of the warlock, instead of my hand rolled reaxes, the

[12:20] rules run on Yara, which is the pattern that engine malware researchers have been using for like 15 plus years. It’s fully deterministic. It’s the same input, same output every single time. It’s boring on purpose. And in security, boring is a feature. So what does the warlock actually catch in the wild today? um a bunch of different stuff, but two of these are an absolute like nuisance to my soul. Uh the first thing is actually not a rule-shaped thing. It was

[12:53] something the uh that the warlock flagged. That was actually a sub aent behavior that exposed a vulnerability to us um based off of what sub agents were doing. Uh so basically we were spinning up agents to do large tasks. They were spawning sub aents and those sub aents were trying to get around the guardrails that we had implemented in the wizard and they were trying to invent secrets. They were trying to pull secrets from quite literally anywhere in the codebase and we shut it down. We said no more sub agents and because of the warlock we

[13:26] caught that. And I’ll empathize with the robot. The robot had a task to do and it was trying to optimize and please us. But we can’t have that. And something else at Post Hog that really matters to us is PII. Uh agents genuinely do not care about uh exposing data unless you make explicit rules. Uh left alone, we watched it dump emails, phone numbers straight into events. And to an agent, that looks like a totally normal thing to capture.

[13:58] And luckily for prompt injection specifically, I’m going to knock on wood here. Uh we have basically never caught an actual malicious prompt injection in the wild, but we do catch a ton of false positives. Things like our demo login screens, copy on our example apps, things in our docs. And it’s actually made me rethink how I build applications and how I write docs because I don’t want to ship anything that looks threatshaped. But the false positives are honestly the perfect setup for the messiest, most

[14:33] interesting part of this whole thing. So this is the part that I wrestled with. I spent this whole talk preaching deterministic to all of you. And then I went and I added an LLM layer to help sort my false positives and silence some of the noise. And I call it triage. When I was building this triage layer, I had to make a choice. Should the layer be a bouncer or should the layer be an adviser? And the easiest choice probably could have been make the LLM the

[15:06] bouncer. Show it the command, ask it is this an attack block allow and just do whatever it says. And while that’s tempting because it seems easier, I can’t uh bet my security model on a coin flip because my model’s having a bad day or something happened and it’s acting different today than it did yesterday. So instead of the bouncer, I crafted the model to be the adviser. And this was the clean line that I found and a line that I’m still exploring, but I want to

[15:37] leave all of you with. Uh for us, detection and enforcement stay deterministic and mechanical. If a rule matches, the gate locks, the session ends, and there is no model anywhere on that path. The block happens before we even ask the LLM’s opinion. The LLM only gets to weigh in afterwards if we have not blocked something. It’s designed to remove noise. It is not designed to let things through. And if it fails clos and it fails closed. So if the model is

[16:08] having a bad day, all wizard runs are killed. Sorry, but we’re just protecting you. Enforcement is the part that you bet the house on. So it has to be deterministic, but judgment is the part that adds nuance. So that’s really the only place that you can put anything probabilistic in there. So, how do we ship real rules for agents? This is the anatomy of one of our warlock rules. And every warlock rule has four parts. Part one is the

[16:42] metadata. It’s plain English description, uh, severity, category, action, uh, direction. Is this flowing into the agent? Is this something the agent is writing? Uh then we have the strings. So these are the actual patterns that you’re looking for. And part three is the condition. So this is where the rule is actually allowed to fire. I’ll walk through this example for you

[17:12] and we can pretend like we’re writing it in our head. Prompt injection being like the classic ignore all previous instructions. Your first instinct here is probably to block uh the word ignore, but agents read code all day and ignore can show up in code comments or examples all the time. So you don’t want to match the verb alone. You match the verb plus an instruction flavored noun. In the condition, you say fire if any of any of those patterns hit. And in the

[17:43] metadata, you determine is this critical? uh what the category is, what the action is, in this case block, and the direction in this case being input flowing into the agent. But to write good rules that reduce noise, you have to ship tests with them. So you have to write tests that say this are these are patterns that match. These are ones that should not. And that negative test is the first line of defense against false positives. But you

[18:14] also want to make sure when you’re deciding the severity of that uh rule that you track real world impact, not how scary it looks. RM-rf is scary, but it’s also how we all delete note modules like 40 times a day. You decide the real world impact for the agent that you’re building because a security tool that crashes every time it tries to clean a build folder is a tool that gets turned off and one that catches absolutely nothing.

[18:48] So I’m proud to say this is our security posture now. I can finally come up here and say we have true defense and depth. Um all my learnings have assembled into this. Uh, it’s still layered, but every layer is doing a job that it’s good at. Now, we still have prompts, but we only use them for steering. Everything runs in a sandbox. We deny by default. We have a vault, so secrets never hit the model. We have the warlock to scan content coming in and to scan output

[19:19] being written by the agent. We also have triage to reduce the noise. And we have telemetry embedded in the entire process so that we see everything. None of these layers stands on its own. Not a single thing here is going to save you. But it’s just boring, honest layers. Each of them doing uh one job that it’s good at. So if you’re building an agent with hands, this is the whole talk in three lines. One, if it isn’t enforced uh

[19:50] deterministically, it is not enforced. Prompts are not security rules. Don’t act like they are. Uh two, the dangerous input uh isn’t just what your user types. It isn’t just the commands that you allow it to run. It’s everything flowing into the model, including the content that you write yourself. So scan your own supply chain at the source and when the agent invokes it. Three, attacks compose. Code review doesn’t. Most of our gaps during our audit were

[20:22] two innocent things shaking hands and opening a door. The wizard, the warlock, and the context mill are all open source. So, come find me downstairs. I’m in the expo hall at our booth, and I’ll show you around uh show you what we built, and I want to hear how you guys are securing your agents. Thank you.