AWS access key leaked: what to do in the first 10 minutes

Assume the key was copied the moment it became public. The order below is the one that limits damage; the console paths and CLI commands come from the IAM and CloudTrail docs and were checked against AWS CLI 2.34.

An AKIA… access key ID and its secret went somewhere they should not have: a public GitHub push, a Slack message, a screenshot, a Docker image, a shell history file. It is widely reported that scrapers find keys in public repositories within minutes, so treat it as already stolen. Work through this list in order. Step 1 is the only one that has to happen right now; the rest is the next ten minutes.

1. Deactivate the key. Do not delete it yet

An inactive key is refused on every request immediately, and the change is reversible. Deleting is permanent, and it removes the key ID you are about to search CloudTrail for. AWS's own rotation procedure deactivates first and deletes later, and this is the one time you should not wait for the "last used" check before doing it.

First confirm which account the key belongs to. This works with any identity and tells you whether to panic about this account or a different one:

aws sts get-access-key-info --access-key-id AKIAIOSFODNN7EXAMPLE

Then deactivate it using credentials that are not the leaked key. If the leaked key is the one your CLI profile uses, do this step in the console or with a different profile:

aws iam list-access-keys --user-name NAME
aws iam update-access-key --user-name NAME --access-key-id AKIAIOSFODNN7EXAMPLE --status Inactive

In the console: IAM, Users, choose the user, Security credentials tab, Access keys, then Actions and Deactivate. A root user key is managed from the root user's own Security credentials page, and should be deleted rather than rotated.

A key starting with ASIA is a temporary credential and expires on its own. To cut it off early, use the role's Revoke sessions tab in the IAM console; see Revoke IAM role temporary security credentials.

2. See whether it was used

Quick answer first. This shows the last date, service and Region the key signed a request for, and it still works on an inactive key:

aws iam get-access-key-last-used --access-key-id AKIAIOSFODNN7EXAMPLE

A last-used date before the leak is good news but not proof. For the real record, open the CloudTrail console, choose Event history, set the lookup attribute to AWS access key and paste the key ID. Three limits of event history matter here, all from the CloudTrail docs:

From the CLI, one Region at a time:

aws cloudtrail lookup-events --region us-east-1 \
  --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIAIOSFODNN7EXAMPLE \
  --query 'Events[].[EventTime,EventName,EventSource]' --output table

Look for anything the key created: CreateUser, CreateAccessKey, CreateLoginProfile, AttachUserPolicy, CreateRole, RunInstances, RequestSpotInstances, and SES or Bedrock calls. Then check the Billing console for a cost spike.

3. Undo what the key created

Deactivating the key does nothing to the extra user, access key or role an attacker made with it; those are the real persistence. For every creation event you found in step 2, delete what it created, and check that no new policy was attached to your own users or roles. A quick inventory:

aws iam list-users
aws iam list-access-keys --user-name NAME
aws iam list-roles --query 'Roles[?starts_with(CreateDate, `2026-10`)].[RoleName,CreateDate]'

Adjust the date prefix to the leak window. If the key had admin rights and you find any of this, assume there is more and open a support case.

4. Rotate, then delete

Create a replacement, switch everything that used the old key, confirm it works, and only then delete the leaked one. Each IAM user can hold at most two access keys, so if the user already had two, deleting the inactive leaked key is how you make room:

aws iam create-access-key --user-name NAME
# update ~/.aws/credentials, CI secrets, .env files, deploy configs
aws iam delete-access-key --user-name NAME --access-key-id AKIAIOSFODNN7EXAMPLE

Ask whether the replacement needs to be a long-term key at all. The IAM docs are blunt about it: prefer roles and temporary credentials, which expire on their own. For a laptop, that usually means IAM Identity Center and aws sso login instead of an AKIA key in ~/.aws/credentials.

5. What AWS and GitHub may already have done

If the key went to a public GitHub repository, you may find a support case and an email from AWS waiting. GitHub runs secret scanning on every public repository, Amazon AWS is a secret scanning partner, and matches of partner patterns in public code are sent to the provider. AWS responds by attaching the managed policy AWSCompromisedKeyQuarantineV3 to the user and opening a case. Three things about that policy:

Push protection would have refused the push in the first place; the AWS key pattern supports it. Turning it on is in GitHub push protection blocked your push.

6. Clean up the copies

The key is dead, so this is tidying, but dead keys keep tripping scanners and get pasted back into use. ~/.aws/credentials is plain text; edit the stale entry out. If you ran export AWS_SECRET_ACCESS_KEY=… in a terminal, it is in .zsh_history, .bash_history or fish history. If it was committed, see how to remove an API key from git history; if it was baked into an image, see secrets in Docker images. The general checklist for other providers is in I leaked my API key, what do I do?