Runbook: credential leak
Rotate or revoke, work out what the leases could reach, and understand why the exposure is bounded.
Trigger. Credential material has appeared somewhere it should not — a support ticket, a chat message, a log you did not expect, a public repository, a screenshot.
#First: what actually leaked?
Two very different situations.
The stored material leaked. Someone pasted the API key. The real downstream secret is out. This is the serious case.
A lease leaked. A short-lived, scoped credential issued for one action appeared in a log. Bad, and bounded: it has already expired or will within minutes, and it was scoped to a single action.
The exposure is bounded, and that is the broker's whole purpose
The agent never held the stored material. It received leases — each short-lived, each scoped to one action, each recorded by reference.
So the question is not "what could that key do" but "what could those leases do during their lifetime". That is a much smaller question, and the action records answer it exactly.
#Rotate, or revoke?
| Use when | Effect | |
|---|---|---|
| Rotate | The downstream account is fine; you want new material | New material sealed, all leases invalidated, tools keep working |
| Revoke | The credential should not exist at all | Terminal; every tool depending on it starts failing |
Rotate is almost always right. It stops the leaked value from being useful without breaking anything that was working.
#Rotate
bash# 1. Create new material at the downstream first.
# 2. Then seal it here.
curl -X POST $CP/v1/credentials/cred_01ABC/rotate \
-H "Authorization: Bearer $KEY" \
-H 'content-type: application/json' \
-d '{ "material": { "api_key": "sk_live_NEW…", "header": "x-api-key" } }'
Rotation invalidates every outstanding lease, so an in-flight action holding an old lease fails rather than continuing with material you have retired. Requires step-up.
Get the material key right
API_KEY reads api_key, apiKey, key or value — plus header and
prefix. Put the secret under a different name and the rotation is refused with
INVALID_CREDENTIAL_REFERENCE.
That refusal is the good outcome. The check exists because this used to succeed
silently: material sealed, action permitted, nothing brokered, downstream 401,
cause two layers away. Rotating under pressure is exactly when you would make
that mistake.
#Revoke
bashcurl -X POST $CP/v1/security/emergency/preview \
-H "Authorization: Bearer $KEY" -H 'content-type: application/json' \
-d '{ "kind": "REVOKE_CREDENTIAL", "target_id": "cred_01ABC" }'
Preview first. The blast radius lists every tool that becomes unusable and therefore every agent that stops working.
bashcurl -X POST $CP/v1/security/emergency/execute \
-H "Authorization: Bearer $KEY" -H 'content-type: application/json' \
-d '{
"kind": "REVOKE_CREDENTIAL",
"target_id": "cred_01ABC",
"reason": "Material published in support ticket SUP-9912",
"confirm_blast_radius": true
}'
Terminal. Tools depending on it fail at stage 10 with
INVALID_CREDENTIAL_REFERENCE.
#Revoke it downstream too
Veefore rotating does not invalidate the old value at your provider
Rotating in Veefore means Veefore stops using the leaked value. It does not tell your payments provider to stop accepting it.
Revoke the old key at the downstream. Until you do, the leaked value still works for anyone who has it, and Veefore has no way to know or prevent that.
#Work out the exposure
bashcurl -s "$CP/v1/credentials/cred_01ABC" -H "Authorization: Bearer $KEY"
Metadata: when it was created, last rotated, and the lease count. Then find what used it:
bashveefore logs --limit 500
veefore audit list --type credential.leased --from 2026-09-01T00:00:00Z
Action records carry the credential lease by reference. For each lease, you can see which agent, which tool, which action, what the parameters were, and what the downstream returned.
Answer three questions:
- Which leases were issued during the exposure window? That is the set that could have been used by whoever has the leaked material.
- What could each one do? A lease is scoped to one action, so the answer is specific rather than "anything the key can do".
- Does the downstream show activity you cannot account for? The Veefore record shows what Veefore brokered. Activity at the downstream that does not match is activity using the leaked material directly.
Point 3 is the one that matters most, and only your downstream's own logs can answer it.
#Open an incident
bashcurl -X POST $CP/v1/incidents \
-H "Authorization: Bearer $KEY" -H 'content-type: application/json' \
-d '{
"title": "payments-api-key material published in SUP-9912",
"severity": "HIGH",
"description": "Material appeared in a customer-visible support ticket at 14:02 UTC. Rotated in Veefore at 14:19, revoked at the provider at 14:25."
}'
Record the times. The exposure window is the thing you will be asked about.
#Then fix the route
The credential leaked somehow. Finding and closing that path is the durable fix.
| How it leaked | Fix |
|---|---|
| In a log line | Add the path to the tool's sensitive_parameters so it is redacted on the way in |
| In an error message surfaced to a user | Veefore error messages never contain secret values — so this came from your downstream or your own handling |
| Pasted into a ticket or chat | Process. And a reminder that nobody should have had the raw value |
| Committed to a repository | npm run quality:audit fails on committed secrets. Add it to your CI |
| In an agent's environment | Move it into the broker. The agent should never have held it |
That last row is the common one, and it is the whole argument for the broker. An agent that holds a key has it in its prompt context, its logs, and whatever the model says next.
#Close out
veefore doctor --strict— reports credentials overdue for rotation.- Check
CREDENTIAL_ANOMALYin the Risk Center for unusual use during the window. veefore audit verify.- Set a rotation schedule if there was not one. Rotation stops being an emergency when it is routine.