Docs
Runbooksince cloud@2026-09-10

A credential leaked

Revoke the credential before you investigate it. This is the order to work in while a value is still exposed.

Stop the thing working before you work out what happened. Revoking is cheap and reversible for a credential, so revoke first and investigate second.

Stop it working

Three revocations exist, and they are not the same size.

What you revokeWhat stopsCan you undo it
One credentialThat credential aloneYes. Issue the identity a new one
The identityEvery credential it holds, at once. Its grants are deletedNo
A keypair caught in a copyThe keypair and every credential it mintedNo. Enroll a new key

Revoke one credential on Machine Identities then All Identities, open the identity, and revoke the credential row. Both revocations need machine:revoke, checked at the environment the identity is bound to. An owner gets a security email either way.

A credential from an exchange lives fifteen minutes. If what leaked was a build log from an hour ago, that credential is already dead and the work here is rotation rather than revocation.

If the leaked thing is a person's pcu_, have them run penv logout, which revokes it. It would otherwise last 30 days from its last use.

Rotate what it could read

A credential is bound to one project and one environment, so the blast radius is every key in that one place. Rotate them, oldest and most sensitive first. See rotate a value.

Values are append-only versions, so a rotation is an ordinary write and the old version stays in the history. Nothing you do here destroys evidence.

Read the log

Open Audit Log and filter. Four actions carry most of the answer:

ActionWhat it tells you
secret.readEvery value opened, with the address and the identity that opened it
secret.revealA value released to an agent session, naming the person who approved it
credential.clonedA bound keypair was used from two hosts. The console shows both counters
credential.driftedA trust stopped matching, usually a repository that was renamed or moved

The actor on a machine entry is the identity. The credential it authenticated with sits in the entry's metadata, so one machine's history stays in one place across a rotation.

A read made with a build credential also stamps the run, and the console is where you read it: the repository, the workflow ref, the workflow ref of the executing job, the run id, the run attempt and the platform actor. That scopes an incident to one execution rather than to every run since the trust was created. The counters on a credential.cloned entry are console-side in the same way, so a workspace streaming its log elsewhere still comes back here for both.

Browsing needs audit:read. Taking a copy away needs audit:export.

When a keypair locked itself out

A copied key already did this for you. The number the two sides keep stopped agreeing, so Penv Cloud revoked the keypair and every credential it minted, wrote credential.cloned naming both numbers, and mailed an owner. penv on the host says:

{
  "error": "cloned",
  "message": "this host's key was seen on another machine, so the identity is locked.",
  "fix": "Issue a new enrolment secret in the console and run penv machine enroll again."
}

There is nothing to revoke. Find where the key was copied before you enroll a new one, or you will be back here. A replay of a request that already succeeded reads as unauthorized instead and revokes nothing, so check the log before you assume a copy.

Close the hole

Ask what carried the value out. A credential in a build log means masking was working around something it cannot cover. A credential on a laptop means a person had one where a machine should have. A credential in a repository means a trust was never set up.

Co-location in a CI job is disclosure. Against a step running beside yours in the same job, no amount of masking helps. What bounds a leaked credential there is its fifteen minute lifetime.

Do it in order

  1. Revoke the credential on Machine Identities then All Identities. Revoke the identity if you cannot tell which credential leaked.
  2. Confirm credential.revoke or identity.revoke is in the audit log with your name on it.
  3. Filter the log for secret.read and secret.reveal by that identity, over the whole life of the credential.
  4. Rotate every value it could reach, oldest and most sensitive first.
  5. Redeploy or restart whatever read those values, so nothing is still holding the old ones.
  6. Retire the old values at whoever issues them.
  7. Fix what carried the credential out, then issue a new one and confirm the pipeline is green.

Stream the audit log