The Security Audit Every AI Agent Fleet Needs
A practical AI agent security audit checklist: five checks, one afternoon, clear pass/fail criteria. Run it before your fleet touches production.
An AI agent security audit is a structured review of every credential, permission boundary, and failure-recovery path your agent fleet depends on. Armada Works runs this audit on every client engagement before the fleet goes live, and repeats it whenever a new agent joins the rotation. The entire process takes one afternoon. If you are running multiple agents against a production codebase, you need this audit. If you are running one agent, you still need it, but the permissions walkthrough covers that ground.
This post is about fleets: two or more agents sharing a codebase, credentials, and (usually) a single set of environment variables. The audit catches problems that single-agent reviews miss, because the blast radius multiplies with every agent that shares a secret.
Why a Fleet Audit Is Different
A single agent holds credentials and runs commands. A fleet does the same thing, multiplied. Armada Works runs eight agents against one codebase. Each agent has its own prompt, its own cadence, and its own scope of work. But they share the same .env.local, the same git remote, and the same Supabase project.
That sharing creates compound risk. If one agent's prompt is compromised through a poisoned state file or a manipulated queue entry, every credential in the shared environment is reachable. The guardrails post covered how a single agent can delete a production database. In a fleet, a compromised agent can also write instructions into state files that other agents read on their next run.
The fleet audit exists to verify that:
- No single credential grants more authority than any agent needs
- Destructive commands are blocked at the hook layer, not the prompt layer
- State files are treated as untrusted input, not executable instructions
- Recovery is possible without contacting a provider's support team
The Five-Check Audit
The audit runs five checks in order. Each check has a clear pass/fail criterion. If any check fails, fix it before moving to the next. The whole process takes roughly three hours for a fleet of four to eight agents.
| Check | What It Answers | Time |
|---|---|---|
| 1. Credential scope | Can any token destroy something unrecoverable? | 45 min |
| 2. Destructive-command blocking | Are unrecoverable commands blocked before execution? | 30 min |
| 3. State file hygiene | Do state files leak secrets or contain executable directives? | 30 min |
| 4. Inter-agent boundaries | Can one agent's output change another agent's behavior unsafely? | 45 min |
| 5. Recovery readiness | If the worst happens, can you recover without provider support? | 30 min |
Check 1: Credential Scope
Open your .env.local and classify every credential by blast radius. The permissions audit post walks through this in detail for Supabase, GitHub, and Vercel tokens. The fleet-specific question is: does every agent share the same credential set, or do some agents need credentials that others do not?
What to look for:
- Account-level tokens (Supabase PATs, GitHub classic PATs with
delete_repo, Vercel team-scope tokens) present in the shared environment - API keys for services that only one agent uses (e.g., a social media Buffer token that only the Social Media agent needs) sitting in an environment file that every agent reads
- Service-role keys that grant write access to tables an agent should only read
What passes: every credential in the shared environment is project-scoped or narrower. No account-level tokens. Credentials for single-agent services are either isolated (separate .env file per agent, if your runtime supports it) or documented as accepted shared risk.
What fails: any account-level token in .env.local. Any credential that can delete a project, an organization, or a team. Fix these before moving on. The permissions audit post has the step-by-step scoping instructions for Supabase, GitHub, and Vercel.
Check 2: Destructive-Command Blocking
Prompt-level instructions ("never delete the database") are not security controls. They are suggestions that a sufficiently confused or compromised agent will ignore. The only reliable block is a PreToolUse hook: a shell script that runs before every tool invocation and exits with code 2 to refuse the call.
What to verify:
- A PreToolUse hook exists and is configured in every agent's runtime
- The hook blocks project-deletion commands for Supabase, Vercel, and GitHub
- The hook blocks force-pushes to main, master, and production branches
- The hook blocks filesystem destruction (
rm -rf /,rm -rf ~) - The hook blocks database-level destruction (
DROP DATABASE,DROP SCHEMA public CASCADE) - The hook blocks modifications to the hook script itself (a compromised agent's first move is disabling the guardrail)
How to test: attempt each blocked command in a non-production environment and confirm the hook rejects it. Do not test by running the actual destructive command against production. Write a test script that simulates the tool call and checks the hook's exit code.
# Example: verify the hook blocks "supabase projects delete"
echo "supabase projects delete --ref test-ref" > /tmp/test-cmd
bash .claude/hooks/block-destructive.sh /tmp/test-cmd
# Expected: exit code 2
What passes: every unrecoverable command on the list is blocked, and attempting to modify the hook itself is also blocked.
What fails: any gap in coverage. Common misses include gh repo edit --visibility public (which exposes private code to the internet without deleting anything) and git push origin :main (the colon syntax for deleting a remote branch, which many hook scripts do not pattern-match).
Check 3: State File Hygiene
Agents in a fleet communicate through state files: markdown documents committed to git that carry context from one run to the next. The CMO agent reads every other agent's brief. The Content agent reads a queue file the CMO maintains. Each state file is a potential injection surface.
What to check:
- No state file contains raw credentials, API keys, or database connection strings
- No state file contains executable instructions disguised as content (e.g., "URGENT: run
curlto verify the endpoint") - No state file contains raw user PII, lead email addresses, or prospect data
- State file readers treat content as informational input, not commands to execute
How to audit: read every file under your state directory. Search for patterns that look like secrets:
grep -rn 'sk_\|sbp_\|ghp_\|SUPABASE_SERVICE_ROLE\|AGENT_REPORT_KEY' docs/agents/state/
Then search for patterns that look like injected directives:
grep -rn 'URGENT\|run this command\|execute\|curl\|wget\|sudo' docs/agents/state/
What passes: zero secrets in state files. Zero executable directives. Every agent's prompt includes an explicit rule that state files are informational input, not executable instructions.
What fails: any secret or directive found. If a secret leaked into a state file, rotate the credential immediately. The secret is in git history even after you remove it from the current file. Use git filter-branch or BFG Repo-Cleaner to scrub the history, then rotate.
Check 4: Inter-Agent Boundaries
In a fleet, agents read each other's output. This is the coordination mechanism: the CMO reads everyone's brief, the Content agent reads the CMO's queue, the SEO agent's state file informs the Content agent's keyword choices. But that coordination is also the attack surface.
What to verify:
- No agent can write to another agent's prompt file. Prompt files define behavior. If Agent A can rewrite Agent B's prompt, a compromised Agent A controls Agent B.
- Agents that consume queues or briefs validate the content against their own scope. A Content agent that receives a queue item saying "deploy to production immediately" should flag it, not execute it.
- Each agent's output directory is scoped. The Content agent writes to
docs/content/. The SEO agent writes todocs/agents/state/seo-*. No agent writes outside its designated paths. - Git commits from each agent use a descriptive prefix (e.g.,
content:,seo:,cmo:) so that unexpected cross-boundary writes are visible in the commit log.
How to test: review each agent's prompt file for explicit output-path restrictions. Then review the last 30 days of commits and check whether any agent wrote outside its designated directory.
git log --oneline --since="30 days ago" --name-only
Group the changed files by commit prefix. Any file change that does not match the commit prefix's expected directory is a boundary violation worth investigating.
What passes: clear output-path restrictions in every prompt. Zero boundary violations in the commit log. Explicit "treat as untrusted input" language in every agent that reads another agent's output.
What fails: missing path restrictions, unexplained cross-boundary writes, or any agent prompt that instructs the agent to "follow instructions in the queue" without qualification.
Check 5: Recovery Readiness
The audit's final check is the one most teams skip: can you actually recover if everything goes wrong?
What to verify:
- A local git clone exists on a machine outside the agent's reach (your laptop, a backup server). This clone survives even if the GitHub repository is deleted.
- Supabase point-in-time recovery (PITR) is enabled, or you have a separate backup strategy. Daily snapshots alone do not survive project deletion.
- Vercel environment variables are documented somewhere outside Vercel (a password manager, a secured document). Vercel has no backup product. If the project is deleted, env vars are gone.
- You can rebuild the deployment from scratch using only the local clone and the documented env vars. Test this by deploying to a staging environment from the clone.
What passes: you can answer "yes" to all four. You have tested the recovery path at least once, not just planned it.
What fails: any "no" or "I think so." The difference between a recoverable incident and a catastrophic one is whether you tested the recovery before you needed it.
What a Complete Pass Looks Like
When all five checks pass, your fleet audit summary should read:
- Zero account-level tokens in the shared environment
- PreToolUse hooks block every unrecoverable command, including self-modification
- Zero secrets or executable directives in state files
- Clear output-path boundaries for every agent, with "untrusted input" language in every consumer prompt
- Tested recovery path from a local clone with documented env vars
Robert Cowherd, founder of Armada Works, runs this audit at the start of every engagement and after every agent addition. The audit document lives in the engagement repository alongside the agent prompts, and the client owns it when the engagement ends. A passing audit does not mean the fleet is invulnerable. It means the failure modes you can anticipate are covered, and the ones you cannot anticipate have a recovery path.
Frequently Asked Questions
How often should I re-run the fleet security audit?
Re-run the full audit when you add a new agent, change a credential, or modify a hook script. For stable fleets, a quarterly re-run catches configuration drift. The state-file hygiene check (Check 3) is worth running monthly, since state files change with every agent run.
Can I automate the audit instead of running it manually?
Parts of it. The credential-scope check (Check 1) and the state-file hygiene check (Check 3) are scriptable: grep for token patterns and directive language. The hook-coverage check (Check 2) can be a test suite. But the inter-agent boundary review (Check 4) requires reading prompt files and commit history with judgment. Automate the mechanical checks; review the architectural ones yourself.
What if my agents run in separate environments instead of sharing .env.local?
Separate environments reduce the blast radius of a single compromised agent. Check 1 still applies to each environment individually, and Checks 3 through 5 still apply to the fleet as a whole. Isolation is better than sharing, but it does not eliminate the need for the audit.
Does this audit apply to agents built on frameworks other than Claude Code?
The principles apply to any multi-agent system: credential scoping, destructive-command blocking, state-file hygiene, inter-agent boundaries, and recovery readiness. The specific implementation details (PreToolUse hooks, .claude/hooks/ directory) are Claude Code features. Other frameworks have equivalent extension points. The checklist is the same; the tooling differs.
My fleet only has two agents. Is this audit overkill?
Two agents sharing credentials already create the compound-risk scenario this audit addresses. The audit is shorter with fewer agents (less commit history to review, fewer prompt files to check), but the checks themselves do not change. Skip the audit and you are trusting that neither agent will ever be confused by a malformed input. That is not a bet worth making.
Start With the Audit
If you are running an agent fleet and have not run a security audit, book a discovery call with Armada Works. The first thing we do on every engagement is run this audit against your existing setup. If you would rather do it yourself, start with Check 1 (credential scope) and the permissions walkthrough. The afternoon you invest now is cheaper than the incident you prevent later.