A tarefa era uma issue, o token podia ler a organização inteira
O GitLost, da Noma Security, mostrou um estranho não autenticado abrindo uma issue pública no GitHub e fazendo o agente de IA do GitHub postar o conteúdo de um repositório privado de volta como comentário público. A injeção de prompt rendeu a manchete. O token do agente, com escopo sobre a organização inteira em vez da única issue que ele triava, definiu até onde o vazamento podia chegar. Essa lacuna entre o que a tarefa precisa e o que o ambiente guarda é a parte que vale levar para casa, e a parte que você pode projetar diferente quando hospeda o agente você mesmo.
Um estranho não autenticado abriu uma issue em um repo público do GitHub, escreveu um parágrafo e esperou. O agente de IA do GitHub leu a issue, entrou nos repositórios privados da organização e postou um README privado de volta como comentário público. O parágrafo foi o gatilho. O token do agente, com escopo sobre a organização inteira em vez da única issue à sua frente, é o motivo de o vazamento ter chegado tão longe.
O time de pesquisa da Noma Security montou uma organização no GitHub do
jeito que muitos times fazem hoje: um punhado de repositórios públicos,
vários privados, e o GitHub Agentic Workflows plugado para cuidar do
trabalho braçal. Os GitHub Agentic Workflows são instruções em Markdown
puro que o GitHub Actions entrega a um agente de IA, apoiado no Claude ou
no Copilot, para que o agente possa triar issues, responder perguntas e
abrir pull requests em nome do time. Então os pesquisadores fizeram o
papel do atacante. Abriram uma issue de aparência comum em um dos
repositórios públicos, esconderam algumas frases extras no corpo, e
deixaram o workflow rodar. O agente leu a issue, buscou o conteúdo de um
README.md de um repositório privado, e o colou em um comentário público
onde qualquer um podia ler.
O atacante não usou senha, nem chave roubada, nem código de exploit, e não há CVE. A Noma chama a técnica de GitLost, reportou-a ao GitHub e publicou com o conhecimento da empresa. O payload inteiro era prosa em inglês em um campo que o agente foi construído para ler.
A issue que respondeu com um repo privado.
A mecânica é curta, e é isso que a torna digna de desenho. Um workflow dispara em um evento, como uma issue sendo aberta ou atribuída. O agente lê o título e o corpo da issue como sua tarefa. Enterradas naquele corpo havia instruções mandando o agente buscar o README de um repositório privado e postá-lo como comentário. O GitHub tinha guardas na frente disso: sandboxing, tokens que são só-leitura por padrão, limpeza de input e uma passada de detecção de ameaças sobre o texto. A Noma tentou variações até uma escapar. Prefixar a requisição maliciosa com a palavra "Additionally" ("Adicionalmente") foi o suficiente para passar pelo filtro, porque o modelo a leu como uma tarefa de continuação em vez de um pedido a recusar. Uma mudança de uma palavra carregou a injeção para o outro lado da linha.
Reformular vence o filtro.
Um filtro que lê o corpo da issue e decide se ele contém um ataque está adivinhando a intenção a partir do fraseado, e o fraseado tem um estoque infinito de variações. A Noma não quebrou o modelo nem achou um bug de memória. Eles reformularam a mesma requisição até o classificador pontuá-la abaixo do próprio limiar, e "Additionally" foi a formulação que acertou.
Essa é a propriedade estrutural dos agentes que usam ferramentas sobre a qual escrevemos semana passada: um agente lê suas instruções e os dados que busca como um único fluxo plano de tokens, e infere qual parte é um comando pelo tom e pela posição, do jeito que uma pessoa lê por alto. O corpo de uma issue é dado. Injeção é o movimento que molda dados não confiáveis com a forma de um comando e aposta que o modelo agirá sobre eles. A detecção ajuda e vale a pena rodar, e ela vai falhar: um classificador tem um limiar, e um atacante com tentativas ilimitadas sonda até um fraseado pontuar abaixo dele.
A lacuna que dimensionou o vazamento.
Uma parte do GitLost sobrevive a qualquer filtro que o GitHub lance a seguir. A tarefa do workflow era triar uma issue em um repositório público. O token que o GitHub Actions colocou no ambiente daquele workflow tinha acesso de leitura a todo repositório público e privado da organização, porque os times concedem essa amplitude para que o agente possa puxar contexto entre repos. O atacante escolheu o alvo; o escopo do token definiu o limite do dano. Reformule o ataque de cem maneiras e esse limite continua o mesmo: tudo o que o token consegue ver.
A própria recomendação da Noma aponta para a mesma costura. O conselho deles aos defensores é restringir o escopo do token ao único repositório que o workflow tria em vez da organização inteira. Esse conselho admite que a injeção às vezes vai acertar, e que, quando acertar, o raio de dano deve ter o tamanho da tarefa em vez do tamanho da conta.
O caminho de exfiltração era o trabalho diário do agente.
O README privado saiu da organização por um comentário público, que é uma coisa que o agente deve mesmo ser capaz de fazer. Comentar em issues é sua função. Nada no fio parecia roubo: nenhum endpoint estranho, nenhum blob codificado saindo por uma porta lateral. Um monitor de rede vigiando tráfego malicioso teria visto o agente postar um comentário, coisa que ele faz o dia inteiro. Quando o canal de exfiltração é uma capacidade sancionada, a defesa que compensa é restringir o que o agente pode alcançar em primeiro lugar.
Onde você pode mudar a arquitetura.
Duas coisas sobre o GitLost estão fora do seu alcance. O bug é do GitHub para corrigir, e o GitHub está trabalhando nele. E o agente rodou nos servidores do GitHub, dentro do GitHub Actions, onde nenhum produto que você instala fica no caminho. O Bromure Agentic Coding roda no Mac de um desenvolvedor. Ele não está na frente do workflow server-side do GitHub e não alega estar. Se sua única exposição a essa classe de problema é um agente hospedado que outra pessoa opera, a alavanca que você tem é a que a Noma nomeou: restrinja o escopo do token.
A lição transferível é para o número crescente de times rodando agentes de codificação em máquinas que eles controlam, onde a arquitetura é sua para definir. Dois princípios atravessam a partir do GitLost, e nenhum depende de pegar a injeção. Mantenha o ambiente enxuto, para que um agente sequestrado herde pouco que valha a pena levar. Restrinja a credencial à tarefa, para que o alcance de um comprometimento tenha o tamanho do trabalho em vez do tamanho da conta. O Bromure Agentic Coding é um arranjo desses princípios.
O Bromure Agentic Coding roda seu agente de
codificação, Claude Code, Codex ou Grok, dentro de uma VM Linux
descartável por perfil: seu próprio kernel, seu próprio sistema de
arquivos, sua própria pilha de rede, a um hypervisor de distância do seu
Mac sobre o framework de virtualização da Apple. Um perfil é um escopo
coerente de trabalho, um cliente ou um serviço. As credenciais reais
nunca entram nessa VM. O Bromure as guarda no host atrás de um broker e
envia ao guest valores falsos que parecem reais para as ferramentas que
os leem; um proxy no seu Mac troca o stub pelo segredo real no fio quando
a requisição sai, e
o sandbox que guardava a chave
percorre o mecanismo. Um agente que é convencido a rodar cat em um
arquivo de credencial encontra um placeholder, porque o valor que ele
queria nunca esteve do seu lado da fronteira.
O token que o agente de fato pode gastar é restrito e expirável, então um vazamento é um uso estreito e limitado no tempo em vez de uma concessão permanente. A área de trabalho inteira é uma VM que some quando você fecha a sessão. Passe a forma do GitLost por esse arranjo e a injeção ainda pode acertar, porque isolamento não desengana um modelo. Um agente convencido a exfiltrar estende a mão para uma credencial e encontra um stub, gasta um token que só cobre o único perfil em que estava trabalhando, e fica em uma caixa sem caminho para o resto da sua máquina. O alcance do comprometimento tem o tamanho da tarefa.
Mantenha o ambiente enxuto
Um agente sequestrado só pode entregar o que seu ambiente guarda. Stubs no guest e segredos reais no host significam que a injeção que acerta encontra placeholders onde esperava chaves.
Restrinja a credencial à tarefa
O conselho da Noma para os workflows do GitHub é o mesmo princípio: um token que cobre um repo limita o dano a um repo. Escopo e expiração transformam um vazamento em um evento estreito e limitado no tempo.
Torne a caixa descartável
Quando a área de trabalho é uma VM que evapora ao fechar, a persistência não tem onde se assentar de forma durável e o raio de dano termina com a sessão.
Assuma que haverá injeção
A detecção vale a pena rodar e vai falhar. Projete para que o resultado de uma falha seja sobrevivível, em vez de apostar em pegar cada formulação.
O que isto deixa de pé.
Restringir escopo não torna um agente seguro para apontar a um segredo real. Se você coloca uma credencial viva dentro da VM e o agente é convencido a lê-la, nenhum hypervisor a des-lê; a mudança está no que o agente pode alcançar, não em se um modelo enganado permanece enganado. O problema de exfiltração que a Noma destacou tem uma parte que o isolamento sozinho também não fecha: um agente que pode postar um comentário, abrir um PR ou enviar uma mensagem pode mover dados para fora por esse canal sancionado, e o escopo decide quanto dado está ao alcance para mover, não se o canal existe. E o GitLost em si pertence ao GitHub. Atualize quando eles corrigirem, e restrinja seus tokens de workflow enquanto isso, porque essa é a alavanca que a plataforma lhe entrega.
Onde quer que você rode um agente, os pesquisadores vão continuar reportando as injeções, e o escopo da credencial no ambiente do agente vai continuar determinando se cada uma termina como um quase-acidente registrado em log ou como um repositório privado em uma página pública. A correção da Noma e a arquitetura do Bromure apontam na mesma direção: dê ao agente o alcance que a tarefa precisa e nada mais amplo.
O Bromure Agentic Coding roda Claude Code, Codex e Grok em VMs Linux descartáveis em Apple Silicon, com as credenciais reais guardadas no host atrás de um broker e trocadas no fio, detecção de injeção de prompt nos inputs do agente, e cada chamada gravada em um trace que o agente não pode editar. É gratuito, open-source e disponível hoje em bromure.io. Com agradecimentos à Noma Security, cujo write-up do GitLost motivou este.