---
title: "O que um desenvolvedor precisa entender sobre agentes de IA com acesso a sistemas reais"
description: "Sandbox, credenciais, menor privilégio, rede e logs: o que muda quando um agente de IA deixa o chat e passa a executar shell, APIs e ferramentas."
date: "2026-09-19"
tags: ["agentes-ia", "seguranca", "sandbox", "menor-privilegio", "devops"]
url: "https://abjr.dev/noticias/agentes-ia-acesso-sistemas-reais"
---

O agente leu o ticket, chamou a API do banco, rodou um comando no shell e respondeu que "já resolveu". No chat, isso parece produtividade. Na infraestrutura, é um processo com identidade, rede e credenciais. A diferença entre um assistente que sugere SQL e um agente que executa o SQL não é de UX. É de superfície de ataque.

Eu uso agentes com ferramentas no dia a dia. O que me interessa neste texto não é o modelo em si. É o que você precisa controlar quando a saída do modelo deixa de ser texto e vira ação: sandbox, credenciais, menor privilégio, isolamento de rede, orçamento de tokens e tempo, allowlist de ferramentas, e logs que sobrevivem a um incidente.

## A cena: shell e API no mesmo loop

Um agente típico com acesso a sistemas reais faz um loop. O modelo recebe o objetivo. Decide uma ferramenta. O runtime executa. O resultado volta para o contexto. O modelo decide de novo. Em dez passos, ele pode ter listado arquivos, lido um `.env`, chamado um endpoint interno e aberto um PR.

Nada disso exige má intenção do usuário. Basta um ticket com texto estranho, um README de terceiro, ou um comentário em issue que o agente "só ia resumir". O OWASP chama isso de *prompt injection* indireto: o conteúdo externo entra no contexto e altera o comportamento do modelo. No chat puro, o pior caso costuma ser uma resposta ruim. Com ferramentas, o pior caso é o agente usar as suas próprias permissões contra o seu sistema.

A pergunta útil não é "o modelo é seguro?". É: se o modelo escolher a ferramenta errada, ou a ferramenta certa com o parâmetro errado, o que ainda é possível?

## O que muda em relação ao chat

No chat, o contrato é geração de texto. Você filtra saída, marca conteúdo sensível, e o dano fica em grande parte na confiança do usuário no que leu. No agente com ferramentas, o contrato é side effect. Delete, deploy, `UPDATE`, envio de e-mail, compra de crédito em nuvem. O modelo não precisa "escapar" do sandbox de texto. Ele só precisa de uma chamada de ferramenta autorizada demais.

Três mudanças práticas:

1. **A identidade deixa de ser a do usuário humano sozinho.** O agente age com um service account, um token de API, um kubeconfig, ou o mesmo segredo que a aplicação usa. Se esse segredo for amplo, o agente herda amplitude.
2. **O contexto mistura fontes com níveis de confiança diferentes.** Instrução do sistema, pedido do usuário, saída de ferramenta, página baixada, e-mail, linha de ticket. O modelo trata tudo como tokens. Não há boundary de confiança automática entre "mensagem do admin" e "anexo do cliente".
3. **O erro deixa de ser só alucinação verbal.** O NIST AI 600-1 trata confabulação e riscos de segurança da informação como categorias distintas, mas no agente elas se encontram: o modelo inventa um caminho de arquivo ou um ID, e a ferramenta executa de verdade.

O OWASP Top 10 for LLM Applications 2025 elevou *Excessive Agency* (LLM06) exatamente por causa dessa mudança. O risco não depende só de o modelo ter sido "hackeado". Basta autonomia demais + ferramenta aberta demais + falha qualquer no raciocínio.

## Superfície de ataque, sem teatro

Desenhe o diagrama mental em três camadas.

**Entrada.** Prompt direto do usuário. Injection indireto via conteúdo que o agente lê (web, repo, ticket, PDF, resposta de API). Metadados de ferramenta (descrições MCP/plugin) que o modelo vê e o humano quase nunca. O cheat sheet da OWASP sobre prompt injection trata saída de ferramenta e conteúdo remoto como não confiáveis, no mesmo espírito em que você trata input de formulário.

**Decisão.** O modelo escolhe ferramenta e argumentos. Aqui entram alucinação de parâmetro, confusão de escopo ("apague o cache" vira `rm -rf`), e chains em que uma observação forjada empurra a próxima ação. Autonomia excessiva sem gate humano em ações de alto impacto amplifica qualquer um desses erros.

**Execução.** Shell aberto, cliente HTTP genérico, SDK da nuvem com role admin, volume montado com o home do desenvolvedor, rede do cluster sem NetworkPolicy. A documentação do gVisor é explícita: container sozinho não é sandbox. Compartilhar o kernel do host significa que um escape de container continua sendo uma classe de risco real. A documentação de sandbox da OpenAI reforça o outro lado: código gerado pelo agente enxerga arquivos, credenciais e rede disponíveis no ambiente. Se o segredo está lá, o agente pode lê-lo.

Casos públicos úteis para calibrar o medo, sem sensacionalismo: pesquisadores mostraram que instruções escondidas em issue/ticket/página podem fazer um assistente com ferramentas privilegiadas extrair dados ou tomar ações que o usuário não pediu. O padrão se repete nos cenários do próprio OWASP LLM01. O vetor não é "IA maligna". É conteúdo não confiável + agente com poder demais.

## Controles que importam de verdade

### Sandbox: isolar a execução, não "confiar no prompt"

Se o agente gera ou executa código, trate o workload como não confiável. Isolamento em camadas:

- **Processo / container** com filesystem mínimo, usuário não-root, cgroups de CPU/memória/disco.
- **Runtime mais forte** quando o código é adverso ou gerado: gVisor (kernel em userspace que intercepta syscalls), ou microVM (Kata/Firecracker) quando você precisa de kernel separado. O gVisor reduz a superfície de System API do host; não substitui política de rede nem controle de segredos.
- **Ambiente efêmero por tarefa ou por tenant.** A OpenAI recomenda compute isolado e ambientes separados quando dados não devem se misturar. Warm pool ajuda a não pagar o custo de segurança em latência, mas o isolamento continua sendo o ponto.

Sandbox limita o que o código *pode* fazer no host. Não limita o que a credencial montada *autoriza* na API de produção. São eixos diferentes.

### Credenciais: fora do alcance do modelo

Regra que eu uso: o modelo nunca vê o segredo longo. A ferramenta confiada injeta o segredo no momento da chamada, ou um proxy/broker troca um placeholder por header real só para hosts aprovados.

Consequências práticas:

- Chave da aplicação (orquestração, audit, vault) fora do sandbox. Chave do executor, se existir, com escopo mínimo e rotacionável.
- Sem `AWS_ACCESS_KEY_ID` no env do container do agente "porque facilita o boto3".
- Preferir credencial de curta duração (STS, workload identity, OAuth com escopo estreito) a chave estática.
- Montar volume com secret ainda expõe o secret ao código do agente. Broker > env var > arquivo no workspace.

O OWASP LLM01 recomenda exatamente isso em mitigação: tokens da aplicação nas funções da aplicação, não entregues ao modelo; privilégio mínimo para a operação pretendida.

### Menor privilégio: IAM e allowlist de ferramentas

*Least privilege* aqui tem duas faces.

**Face IAM.** Role do agente ≠ role do humano admin ≠ role da app monólito. Se o agente só precisa ler `orders` e criar issue no tracker, a policy para aí. O NIST SP 800-207 (Zero Trust) formula o princípio de forma útil para agentes: autenticação e autorização por sessão/pedido, com o mínimo de privilégio necessário para aquela ação, sem confiança implícita porque "já está na VPC".

**Face ferramentas.** O LLM06 é direto: minimize extensões; evite extensões abertas (`run_shell`, `fetch_url` genérico) quando dá para oferecer uma função estreita (`write_report_file`, `get_order_by_id`). Allowlist por agente, por ambiente e, se possível, por usuário. "Todas as tools do catálogo" é o equivalente a `SELECT *` com user `postgres`.

Ações irreversíveis ou caras (drop, deploy prod, refund, envio em massa) pedem human-in-the-loop. Não como teatro de UX: como gate no runtime que rejeita a tool call sem aprovação, mesmo que o modelo "tenha certeza".

### Isolamento de rede

Sandbox sem egress control ainda fala com o metadata service da nuvem, com o banco interno, com o webhook do atacante. Controles concretos:

- Allowlist de egress (DNS e IP) para o que a tarefa precisa.
- Bloquear acesso a link-local / IMDS quando o agente não precisa assumir role pela instância.
- Separar rede do sandbox da rede de produção: o agente fala com um gateway seu; o gateway fala com produção com política própria.
- Em Kubernetes, NetworkPolicy não é opcional se o pod executa código do modelo.

O gVisor deixa claro que política de rede continua sendo responsabilidade do orquestrador. O sandbox não configura isso por você.

### Orçamento de tokens, tempo e chamadas

Agente sem teto entra em loop, gasta API, martela endpoint, ou tenta a mesma mutação até dar certo do jeito errado. Defina:

- máximo de passos (tool calls) por sessão;
- timeout wall-clock por run;
- rate limit por ferramenta e por identidade;
- circuit breaker: N falhas ou N ações de alto impacto e o run morre;
- teto de custo (tokens + chamadas externas).

Isso não é otimização financeira só. É contenção de blast radius quando o modelo decide "tentar de outro jeito" cinquenta vezes.

## Logs e auditoria: o que precisa existir depois do incidente

Se você não consegue responder "quem/o quê autorizou qual tool call com quais argumentos", você não tem agente em produção. Tem um processo opaco com side effects.

O mínimo útil:

- **Identidade do agente** (não só "o bot"): versão do prompt/system, modelo, ambiente, tenant, usuário solicitante.
- **Cada tool call**: nome, argumentos (com redaction de segredo), resultado resumido, latência, decisão (permitido / negado / aguardando aprovação).
- **Cadeia de contexto**: hash ou id do conteúdo externo que entrou no prompt (issue, URL, arquivo), para investigar injection indireto.
- **Aprovação humana**: quem aprovou, o quê, quando.
- **Imutabilidade razoável**: log em sistema que o próprio agente não pode apagar com a mesma credencial.

O NIST AI 600-1 enfatiza inventário de sistemas de IA, papéis de supervisão humana e monitoramento pós-deploy. Em agente com ferramentas, inventário significa: lista de tools, destinos de rede, roles IAM e owners. Sem isso, o checklist de segurança vira slide.

Log demais também vaza. Redacte token, cookie, corpo de resposta com PII. Guarde argumento bruto só onde a política de retenção e acesso forem explícitos.

## Checklist de produção

Antes de apontar o agente para algo que dói se der errado:

- [ ] O agente tem identidade própria no IAM; não reutiliza a role admin da equipe.
- [ ] Cada ferramenta é necessária; shell/URL genéricos estão justificados ou foram substituídos por funções estreitas.
- [ ] Credenciais longas ficam fora do sandbox; broker ou handler da ferramenta injeta o segredo.
- [ ] Egress é allowlist; IMDS e redes internas sensíveis estão bloqueados por padrão.
- [ ] Sandbox isola filesystem e, se executa código gerado, usa runtime reforçado (gVisor/microVM) além de container.
- [ ] Há teto de passos, tempo, rate limit e circuit breaker.
- [ ] Ações de alto impacto exigem aprovação humana no runtime, não só "por favor não faça isso" no system prompt.
- [ ] Tool output e conteúdo externo são tratados como não confiáveis na reentrada do contexto.
- [ ] Audit log cobre tool calls, negações e aprovações; o agente não pode apagar o próprio rastro.
- [ ] Existe kill switch: revogar credencial, derrubar o runner, desligar a allowlist sem redeploy heroico.
- [ ] Ambiente de staging com as mesmas guardas, e teste adversário (injection indireto em ticket/README) faz parte do release.

System prompt ajuda a orientar. Não é controle. Controle é o que o runtime recusa mesmo quando o modelo insiste.

## O ponto em que vale parar

Agente com acesso a sistemas reais é útil quando o efeito colateral está contido e observável. É má ideia quando a primeira versão já tem `kubectl`, billing da nuvem e o mesmo token do CI. Comece estreito: uma ferramenta, um destino, um ambiente, logs ligadas. Amplie privilégio só com evidência de que as guardas aguentam o caso feio, não só o demo feliz.

O chat responde. O agente age. A engenharia boa trata a segunda frase com o mesmo rigor que você já trata um worker com credencial de produção.

Se o seu agente pudesse executar uma única ferramenta amanhã, qual você escolheria — e qual privilégio ela *não* precisaria ter?

## Referências

- [OWASP Top 10 for LLM Applications 2025 (PDF)](https://genai.owasp.org/download/43299/) — LLM06:2025 Excessive Agency (minimizar extensões, evitar tools abertas, menor privilégio, human-in-the-loop, rate limiting). Versão web equivalente: [LLM08 Excessive Agency (2023/24)](https://genai.owasp.org/llmrisk2023-24/llm08-excessive-agency/).
- [OWASP LLM01:2025 Prompt Injection](https://genai.owasp.org/llmrisk/llm01-prompt-injection/) — injection direto e indireto; impacto sobe com a agência do sistema.
- [OWASP Cheat Sheet: LLM Prompt Injection Prevention](https://cheatsheetseries.owasp.org/cheatsheets/LLM_Prompt_Injection_Prevention_Cheat_Sheet.html) — validação de tool calls, least privilege, dual-LLM / segregação de conteúdo não confiável.
- [gVisor Security Model](https://gvisor.dev/docs/architecture_guide/security/) — containers não são sandbox; redução da superfície de System API; rede e cgroups continuam no host/orquestrador.
- [OpenAI: Sandbox security](https://developers.openai.com/api/docs/guides/agents-api/environments/security) — isolamento de workload, restrição de rede, separação de credenciais e broker para segredos de terceiros.
- [NIST AI 600-1: Generative AI Profile](https://nvlpubs.nist.gov/nistpubs/ai/NIST.AI.600-1.pdf) — perfil do AI RMF para GenAI: inventário, supervisão humana, monitoramento e riscos de segurança da informação.
- [NIST SP 800-207: Zero Trust Architecture](https://nvlpubs.nist.gov/nistpubs/specialpublications/NIST.SP.800-207.pdf) — menor privilégio por sessão/pedido e redução de zonas de confiança implícita (aplicável a identidades de agente).
- [GKE / Agent Sandbox com gVisor](https://codelabs.developers.google.com/codelabs/gke/ai-agents-on-gke) — isolamento de kernel para código de agente + NetworkPolicy para egress.
