Skip to main content
You pushed a key to a public repository, pasted one into a chat, or found one in a log that more people can read than you thought. This page is the order of operations. Read the first section, do it, then read the rest.

Do this first: revoke, do not rotate

Revoke the exposed key. Do not rotate it. That distinction is the single most important thing on this page, because the two look interchangeable and are not: Rotation exists so you can swap a key in a running deployment without an outage, and the grace window is the whole point of it. In a leak, that same window is 24 more hours of access for whoever has your key. Rotation is the routine path and it is the wrong path here. If you rotate anyway, because a hard cutover would take something important down, then rotate with graceMs: 0. That invalidates the old token immediately and gives you the new one in the same call. graceMs accepts any integer from 0 up to 72 hours, so the safe value is available and it is not the default.

How to revoke, today

Which route you have depends on your org. If your org manages keys from the hosted product’s API keys page, revoke it there, in the same account you created the key from. Create, rotate, revoke and narrowing to a device subset are all on that page. This is the fastest route when you have it, and it needs nobody’s working hours. Otherwise, ask. Key issuance and revocation on this surface run through an operator channel: reply on your onboarding thread, or use the security contact below, and say plainly that a key is exposed and must be revoked now. Include the key’s id, never the token itself. A revoked key is refused from the next request onwards, and a request holding it fails with revoked_key.
The /v1/api-keys endpoints can do all of this without a human, but they are reached by an OAuth admin in your org, and no authorization server is attached to this surface yet. That is why the operator channel is still the route that is guaranteed to be available to every org. See Getting a key.

Security contact

This section is not filled in yet. The security contact address and the response time commitment are pending. Until they are published here, use your onboarding thread as the reporting channel and mark the message urgent.

Then work out what the key could do

A key is not all keys. Before you assume the worst, check what this one was scoped to, because the answer changes how much you have to unwind.
  • Scopes. A key carries a scope set, and a tool outside it is not merely refused, it is never registered on the connection. A key without an action scope could not have touched a device.
  • Device narrowing. A key can be narrowed to a subset of your devices. A narrowed key could not see, let alone drive, anything outside that subset.
  • Expiry. A key has an expiry, and an expired key is refused with expired_key. If the leak is older than the key, the exposure window closed on its own.
Read those off the key’s record rather than assuming. See Auth and scopes.

What you cannot reconstruct today

Say it here rather than let you discover it during an incident. Receipts record what happened to a device: the org, the device, the idempotency key, the backend kind, the action, a summary of its arguments, the frame it was bound to, the outcome and the timestamps. What a receipt does not record is which key made the call. There is no actor or key id on the ledger, so “what did this specific key do” is not a question this surface can answer yet. The one signal that exists is lastUsedAt on the key itself, and it is worth knowing that it lags, so a quiet key is weak evidence rather than proof of an unused one. Two consequences follow, and both point the same way:
  1. Treat the exposure window as everything the key was scoped to reach, for the whole time it was valid, rather than trying to narrow it from the ledger.
  2. Revoke first and investigate second. Investigation is the part that is currently limited; revocation is not.

A leaked run token

A run token is a credential too, and it is the whole url rather than a header, which is why it ends up in logs and issue threads more easily than a key does. A run token is bound to one device, one lease and one run. It cannot be used to reach another device in your org, and it expires. Ending the run ends the token’s usefulness: cancel the run, and a request carrying that token is refused the same way an unknown one is. See VRX device channel.