Agentic Security: Why Containment Is the Weakest Layer

Data center server racks with network cables illustrating AI agent isolation and security infrastructure

You gave a Claude-based agent write access to a Postgres instance last month. It works. It also has the same credentials as three other agents, none of them are sandboxed, and if any one of them gets prompt-injected through a customer email, your incident response plan is "hope."

That's not a strawman. Across 116 enterprises running agents in production, a majority have already logged a confirmed agent security event or a near-miss. Two-thirds enforce scoped permissions at runtime. Fewer than one in five isolate their highest-risk agents. Credential sharing persists across nearly two-thirds of deployments. The autonomy is scaling faster than the containment.

This post is a practical playbook for the layer most teams are skipping: isolation. Permissions get you halfway. Sandboxing is what keeps a compromised agent from becoming a compromised environment.

The state of agent security in production

Here's the honest read: enterprises are shipping agents faster than they're hardening them. Runtime permission enforcement is now the default (about 66% of deployments), but isolation of high-risk agents — the containment layer that assumes permissions will fail — sits at roughly 18%. That gap is the entire attack surface.

The three failure modes showing up in post-mortems:

  1. Shared credentials across agents. One service account, one API token, five agents. When one agent misbehaves, blast radius is the whole account.
  2. Ambient tool access. Agents can call any MCP server on the host, not a whitelisted subset.
  3. No egress control. Compromised agents exfiltrate to arbitrary domains because nobody put a firewall between the agent process and the internet.

If you build agents that touch production data, customer PII, or money movement, the threat model has changed. You are no longer defending a deterministic service. You are defending a probabilistic decision-maker that can be socially engineered by anything it reads.

Threat model: what actually goes wrong

Before you spend a sprint on hardening, know what you're hardening against. Agent incidents in production cluster into five categories:

Threat What it looks like Primary defense
Prompt injection Malicious content in email, PDF, web page, or DB row hijacks the agent Input isolation + tool scoping
Excessive permissions Agent has DROP TABLE when it only needs SELECT Least-privilege IAM, per-agent creds
Credential leakage Agent leaks API keys via logs, errors, or tool output Secrets brokers, redaction, no keys in prompts
Lateral movement Compromised agent uses network to hit internal services Egress allow-lists, network policy
Data exfiltration Agent posts sensitive data to attacker-controlled endpoint Egress filtering + DLP on tool outputs

Notice that four of the five are contained by isolation, not by permissions. Permissions tell an agent what it's allowed to do. Isolation limits what happens when the permission model gets bypassed — and with LLM-driven agents, it will.

OWASP's LLM Top 10 lists prompt injection (LLM01) and excessive agency (LLM06) as the top two risks for a reason: they're both effectively unpatched at the model layer. You mitigate them structurally, outside the model.

Layer 1: Scoped permissions at runtime

Two-thirds of enterprises get this right. If you're not one of them, start here — it's the highest-ROI hour you'll spend this quarter.

The rule: one agent, one identity, one scoped credential. No shared service accounts. No "admin" role because it was faster to set up.

Concrete example for a Postgres-touching agent:

-- Bad: agent uses app_user which owns the schema
GRANT ALL ON DATABASE prod TO app_user;

-- Good: dedicated role, read-only, row-level scope
CREATE ROLE agent_invoice_reader LOGIN PASSWORD :env_password;
GRANT CONNECT ON DATABASE prod TO agent_invoice_reader;
GRANT USAGE ON SCHEMA billing TO agent_invoice_reader;
GRANT SELECT ON billing.invoices, billing.customers TO agent_invoice_reader;

-- Row-level policy: only invoices this tenant is scoped to
ALTER TABLE billing.invoices ENABLE ROW LEVEL SECURITY;
CREATE POLICY agent_tenant_scope ON billing.invoices
  FOR SELECT TO agent_invoice_reader
  USING (tenant_id = current_setting('app.current_tenant')::uuid);

For cloud IAM, the same idea. Each agent gets its own IAM role, its own audit trail, its own revocation path. When something goes wrong at 2 a.m., you rotate one credential, not thirty.

If you're on the Anthropic stack, Claude Code's permission system is a decent mental model: allow-lists for specific tools, deny-lists for filesystem paths, explicit prompts for anything destructive. Port that mindset to your production agents even if you're not using Claude Code directly.

Layer 2: Sandboxing the high-risk agents

This is the layer where 82% of enterprises are underinvested, and it's the one that actually saves you when Layer 1 fails.

A "high-risk agent" is any agent that meets one of:

  • Ingests untrusted input (email, web scraping, user-uploaded files)
  • Executes generated code
  • Has write access to production systems
  • Handles PII, PHI, or payment data
  • Runs unattended (no human-in-the-loop for individual actions)

For those agents, you need process-level isolation. The minimum viable version: a container per agent invocation, with a read-only root filesystem, no network by default, and an egress proxy that logs and filters every outbound request.

Here's a stripped-down docker run that gets you 80% there:

docker run --rm \
  --name agent-run-${RUN_ID} \
  --network agent-egress-only \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid,size=256m \
  --cap-drop=ALL \
  --security-opt=no-new-privileges \
  --pids-limit=256 \
  --memory=2g --cpus=1.0 \
  -e AGENT_TOKEN=${SCOPED_TOKEN} \
  -v $(pwd)/workspace:/workspace:rw \
  agent-runtime:pinned-sha256

What each flag buys you:

  • --read-only + tmpfs: agent can't persist anything outside /workspace and /tmp. Post-run cleanup is trivial.
  • --cap-drop=ALL + no-new-privileges: no privilege escalation, even if the container is breached.
  • --network agent-egress-only: custom bridge network with an egress proxy in front. No arbitrary outbound.
  • --pids-limit + memory/cpu caps: prompt-injection-driven fork bombs go nowhere.
  • Pinned image digest, not a floating tag: supply chain doesn't move under you.

For stronger isolation on the same box, wrap it in gVisor (--runtime=runsc) or run each agent in a Firecracker microVM. The overhead is measured in tens of milliseconds; the containment is qualitatively different.

For code-executing agents (the highest-risk class), don't run generated code in the same container as the orchestrator. Spin an ephemeral sandbox per execution. Everything runs, output comes back as text, container gets destroyed. That's the pattern behind services like E2B or Modal sandboxes, and you can build a minimal version in a weekend.

Layer 3: Egress control and DLP

Even a well-sandboxed agent needs to talk to something — the model API, its designated MCP servers, maybe one or two SaaS endpoints. Every other destination should be blocked at the network layer.

A minimum egress policy for an invoice-processing agent:

# egress-allowlist.yaml
allowed_destinations:
  - host: api.anthropic.com
    ports: [443]
  - host: mcp.internal.company.com
    ports: [443]
  - host: api.stripe.com
    ports: [443]
    methods: [GET]  # read-only, no charges
default: deny
log_all: true

Enforce this with a squid/envoy proxy in front of the sandbox network, or with Kubernetes NetworkPolicies if you're on k8s. The point isn't the specific tool — it's that a compromised agent trying to POST customer data to attacker.evil gets blocked, logged, and paged, rather than succeeding silently.

Pair egress control with output filtering on the way back in. If a tool returns a blob of text that will be fed into the model's next turn, run it through a redactor that strips patterns matching your credential formats, tokens, and known PII shapes. This is imperfect — regexes miss things — but it catches the obvious footguns.

Layer 4: Credential hygiene

Nearly two-thirds of enterprises have agents sharing credentials. Fix this and you close the biggest lateral-movement path in your stack.

The pattern that works:

  1. No secrets in prompts, ever. If an agent needs an API key, it calls a broker at runtime with its own identity, gets a short-lived token, uses it, discards it.
  2. Per-agent, per-tenant, per-invocation scoping. The token issued to agent-invoice-reader for tenant-42 at 14:03:22 is only valid for that tenant's invoice data, for the next 5 minutes.
  3. Rotate on any anomaly. If your egress logs show unexpected destinations, rotate every credential that agent touched in the last hour. Automate this.

For secrets brokering, HashiCorp Vault with dynamic secrets is the mature choice; AWS Secrets Manager with short-lived STS tokens works if you're all-in on AWS. The specific tool matters less than the pattern: agents never hold long-lived credentials, and every credential is scoped to a single agent's identity.

Layer 5: Audit, replay, and incident response

When something goes wrong — and with agents in production, it will — you need to reconstruct what the agent saw, decided, and did. Without complete audit logs, you can't tell a prompt injection incident from a model hallucination from a legitimate action gone wrong.

Log the full triple for every agent turn:

{
  "run_id": "run_01H8...",
  "agent_id": "invoice-reader-v3",
  "tenant_id": "tenant-42",
  "turn": 7,
  "timestamp": "2026-09-05T14:03:22Z",
  "input": {
    "messages": ["..."],
    "tool_results": ["..."]
  },
  "model_output": {
    "content": "...",
    "tool_calls": [
      {"name": "sql_query", "arguments": {"query": "SELECT ..."}}
    ]
  },
  "tool_execution": {
    "sql_query": {
      "result_rows": 42,
      "duration_ms": 87,
      "credential_id": "cred_01H8..."
    }
  },
  "egress_calls": []
}

Store these immutably (S3 with object lock, or equivalent). When an incident happens, you can replay the exact sequence, identify the injection vector, and — critically — determine blast radius by querying every action that agent took while the compromised credential was live.

Have a written runbook for agent incidents. At minimum: how to disable an agent immediately, how to rotate its credentials, how to query "what did agent X do between times Y and Z," how to notify affected tenants. If you can't answer those four questions in under 15 minutes, you don't have an incident response plan — you have a wish.

A pragmatic maturity ladder

Not every agent needs microVM isolation on day one. Match the containment to the risk.

Tier Agent type Minimum controls
L1 Read-only, internal data, human-approved actions Scoped creds, audit logs
L2 Read/write internal data, no untrusted input L1 + container isolation, egress allow-list
L3 Ingests untrusted input OR writes to prod L2 + gVisor/microVM, output DLP, per-run ephemeral sandbox
L4 Executes generated code OR handles payments/PHI L3 + separate execution sandbox, mandatory human approval for irreversible actions, real-time anomaly alerts

The mistake most teams make is treating every agent as L1 because that's how they started. As soon as an agent touches customer email, uploaded PDFs, or web content, it's L3. As soon as it can rm, DELETE, or move money, it's L4. Reclassify quarterly.

How BizFlowAI approaches this

We ship agents for SMBs that don't have a security team, so the defaults have to be right the first time. Every agent we deploy runs in its own sandboxed process with a scoped MCP toolset — no ambient access to the host, no shared credentials with other agents, an egress allow-list that only includes the endpoints the agent actually needs. High-risk agents (code execution, untrusted input, write access to production) run in ephemeral containers per invocation with a read-only root filesystem and full audit logging.

If you're running agents in production and you can't answer "what happens when this one gets prompt-injected" in a single sentence, that's the conversation to have. Book a discovery call and we'll walk through your current agent stack, identify which tier each agent belongs in, and show you what the containment layer would look like — whether we build it with you or you build it yourselves from the playbook above.

The takeaway

Permissions are the easy layer. Two-thirds of enterprises have them. The reason incidents still cluster in that same population is that permissions are a policy control — they assume the agent behaves within its granted scope. Prompt injection breaks that assumption on a Tuesday afternoon, through a customer support email nobody read.

Isolation is the layer that doesn't assume. It puts the agent in a box where a full compromise still can't reach the database, can't call attacker-controlled endpoints, can't exfiltrate what it can't see. Fewer than one in five enterprises are doing it, which means the teams that do it now have a real security posture in a market that mostly doesn't.

Start with the highest-risk agent in your stack. Get it into a container with an egress allow-list this week. Add gVisor next week. Rotate its credential to a per-agent identity the week after. Three sprints, and you've moved from the 82% who are exposed to the 18% who aren't.


Work with BizFlowAI

If you'd rather have this built for you, that's what we do: production AI automation for solo founders and small teams — agents, integrations, and document pipelines that actually ship.

Book a free discovery call — 30 minutes, we map the highest-ROI automation in your workflow. No pitch deck, just engineering.

More guides like this on the BizFlowAI blog.

Frequently asked questions

How do you sandbox an AI agent in production?

Run each agent invocation in an ephemeral container with a read-only root filesystem, dropped Linux capabilities, no-new-privileges, and strict CPU/memory/PID limits. Attach it to a custom network with an egress proxy that only allows whitelisted destinations. For stronger isolation, wrap the container in gVisor or a Firecracker microVM. Code-executing agents should run generated code in a separate ephemeral sandbox, not in the orchestrator's container.

What is the biggest security risk with LLM agents?

Prompt injection combined with excessive agency is the top risk, as listed in OWASP's LLM Top 10 (LLM01 and LLM06). Malicious content in emails, PDFs, web pages, or database rows can hijack an agent that has broad permissions or shared credentials. Neither risk is patchable at the model layer, so they must be mitigated structurally through isolation, scoped permissions, and egress filtering.

Why isn't scoped permissions enough for AI agent security?

Permissions define what an agent is allowed to do, but LLM-driven agents can be socially engineered by any input they read, so the permission model will eventually be bypassed. Isolation limits the blast radius when that happens by containing the process, blocking arbitrary network egress, and preventing lateral movement. About 66% of enterprises enforce runtime permissions but only 18% isolate high-risk agents, leaving a large attack surface.

How should AI agents handle API credentials?

Never put secrets in prompts. Each agent should have its own identity and call a secrets broker at runtime to receive a short-lived, per-tenant, per-invocation token that expires within minutes. Avoid shared service accounts so that compromise of one agent doesn't expose others. Rotate credentials automatically on any anomaly detected in egress logs or audit trails.

What counts as a high-risk AI agent that needs sandboxing?

An agent is high-risk if it ingests untrusted input like email or user-uploaded files, executes generated code, has write access to production systems, handles PII, PHI, or payment data, or runs unattended without human review of individual actions. Any agent meeting even one of these criteria needs process-level isolation with a container, egress allow-list, and output redaction, not just scoped permissions.