---
title: 'Runbook: credential leak'
description: Rotate or revoke, work out what the leases could reach, and understand why the exposure is bounded.
label: Credential leak
---

**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.

:::security 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.

:::danger 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.

[Full table](/build/broker-a-credential).
:::

### Revoke

```bash
curl -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.

```bash
curl -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

:::danger 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

```bash
curl -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:

```bash
veefore 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:

1. **Which leases were issued during the exposure window?** That is the set that could have been used by whoever has the leaked material.
2. **What could each one do?** A lease is scoped to one action, so the answer is specific rather than "anything the key can do".
3. **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

```bash
curl -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_ANOMALY` in 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.

## Related

:::cards

:::card Credential broker | /concepts/credentials
How leases bound the exposure.
:::

:::card Broker a credential | /build/broker-a-credential
Material keys, and moving a key out of an agent.
:::

:::card Secrets | /secure/secrets
Every place a secret could surface.
:::

:::card Emergency controls | /operate/emergency-controls
`REVOKE_CREDENTIAL` and its blast radius.
:::

:::
