Runbook: compromised agent
Contain first, investigate second, revoke only when you are sure — because revocation is terminal.
Trigger. An agent is doing something it should not: volume well above baseline, destinations nobody configured, repeated refusals, or a key you have reason to believe is exposed.
#Contain first
Isolate the agent
bashcurl -X POST $CP/v1/security/emergency/preview \
-H "Authorization: Bearer $KEY" -H 'content-type: application/json' \
-d '{ "kind": "ISOLATE_AGENT", "target_id": "agt_01JAV…" }'
curl -X POST $CP/v1/security/emergency/execute \
-H "Authorization: Bearer $KEY" -H 'content-type: application/json' \
-d '{
"kind": "ISOLATE_AGENT",
"target_id": "agt_01JAV…",
"reason": "Refund volume 8x baseline with no corresponding claim volume",
"confirm_blast_radius": true
}'
ISOLATE_AGENT rather than PAUSE_AGENT: isolate cuts existing sessions
too, not just new actions. If something is actively using the identity, pause
alone leaves the current session running.
Do not revoke yet
Revocation is terminal and there is no un-revoke. You cannot yet distinguish a compromise from a bug in your own agent, and the two have very different responses. Isolate is reversible and stops the harm just as fast.
If several agents are involved, pause the environment
bashcurl -X POST $CP/v1/environments/env_01ABC/pause \
-H "Authorization: Bearer $KEY" -H 'content-type: application/json' \
-d '{ "reason": "Multiple agents showing anomalous refund volume" }'
Over-broad on purpose. Stopping too much for ten minutes is cheaper than stopping the wrong thing while the right thing continues.
Do not drop the enforcement mode. OBSERVE stops refusing anything while
leaving everything running — the exact opposite of containment.
Open an incident
bashcurl -X POST $CP/v1/incidents \
-H "Authorization: Bearer $KEY" -H 'content-type: application/json' \
-d '{
"title": "finance-agent refund volume 8x baseline",
"severity": "HIGH",
"description": "Volume rose sharply at 02:14 UTC with no corresponding claim volume. Agent isolated at 02:31.",
"affected_agent_ids": ["agt_01JAV…"]
}'
HIGH means contained, not worried. Severity should reflect what you have done.
An open incident also makes trust.active_incidents > 0, so any rule testing it
applies immediately — which is why that rule is worth having before you need it.
See Incidents.
#Investigate
What did it actually do?
bashveefore logs --agent agt_01JAV… --limit 500
Then the full lineage on anything interesting:
bashcurl -s $CP/v1/actions/act_01ABC -H "Authorization: Bearer $KEY"
Read: the delegation chain it acted under, the policies consulted, the rules that matched, the risk signals, the destinations, and the downstream statuses.
Was it authority or behaviour?
Two very different findings.
Authority was exceeded and refused. AUTHORITY_EXCEEDED or ACTION_BLOCKED
in the log means enforcement held. The agent tried and failed. Bad behaviour,
contained.
Authority was sufficient and the actions succeeded. The agent did something harmful within what it was granted. Enforcement worked as configured and the configuration was wrong. That is a policy and delegation problem, and the fix is narrower grants — not a tighter agent.
bashcurl -s $CP/v1/agents/agt_01JAV…/authority -H "Authorization: Bearer $KEY"
Read the resolved authority. This is frequently the moment someone discovers a ceiling nobody intended.
Was the identity used from somewhere unexpected?
bashveefore audit list --type agent.authenticated --from 2026-10-03T00:00:00Z
Session records carry the source address and the reported SDK. An authentication from an address your agent does not run at is the difference between "our agent misbehaved" and "someone else has the key".
Also check authentication failures:
promqlsum by (reason) (increase(veefore_authentication_failures_total[6h]))
A spike in nonce_replayed means someone replayed a captured assertion, which
is a strong signal of interception.
Which credentials were brokered?
The action records list credential leases by reference. Anything the agent reached is a credential whose downstream may have been used.
Note that the agent never held the material — it received brokered leases, each short-lived and scoped to one action. The exposure is bounded to what those leases could do during their lifetime, not to the credential's whole lifetime. That bound is the point of the broker.
#Decide
| Finding | Response |
|---|---|
| Bug in your agent | Fix the agent. Resume. Keep the incident open until deployed |
| Authority too broad | Narrow the delegation and the policy. Resume |
| Prompt injection, bounded by policy | Enforcement worked. Tighten the rule, resume |
| Identity used from an unexpected place | Revoke. Go to the next section |
| Key material exposed | Revoke. Go to the next section |
#Revoke, if it comes to that
bashveefore agents revoke agt_01JAV… --reason "Identity used from an unrecognised address; see inc_01JAV…"
The CLI shows the full blast radius — sessions, cascading delegations, abandoned approvals — and requires step-up. It is terminal.
Then:
Rotate everything the agent could reach
Every credential attached to a tool the agent was authorized for. Not only the ones it used — you are no longer certain what it could see.
bashcurl -X POST $CP/v1/credentials/cred_01ABC/rotate \
-H "Authorization: Bearer $KEY" -H 'content-type: application/json' \
-d '{ "material": { "api_key": "…", "header": "x-api-key" } }'
Register a replacement agent
bashveefore init --name finance-agent-2 --capability refund.create
A new key pair, generated locally. Grant it the narrowest authority that works — this is the moment to fix whatever was too broad.
Check for lateral reach
bashcurl -s $CP/v1/delegations/graph -H "Authorization: Bearer $KEY"
Did the compromised agent hold delegations it could have issued onward? The cascade handles the grants it made, but look at what it could have made and at what else shares its credentials.
#Close out
- Write what you found on the incident. An incident closed with no note teaches nothing.
- Close the incident, which lifts the rules that depended on it.
- Record trust evidence if a review was done.
veefore doctor --strict.veefore audit verify.- Ask: would a narrower delegation have prevented this? Usually the answer is yes, and that is the durable fix.