Home / AWS

AWSRunbookAdvanced

Sev1: AWS access keys leaked or compromised — contain, investigate, recover

Respond to leaked IAM access keys or a compromised role. Deactivate keys, revoke active sessions, find what the attacker did with CloudTrail, clean up created resources and stop long-lived keys from coming back.

Deepak Bhardwaj3 min read

Applies toAWS IAM users and roles, AWS CloudTrail, GuardDuty, AWS CLI v2

Signals

  • An AWS Support case or Health event about exposed credentials (AWS may attach a quarantine policy to the user).
  • GuardDuty findings such as UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration or unusual API calls.
  • A key spotted in a public repository, a container image or a ticket.
  • Unexpected EC2 instances in unused regions (crypto-mining), or a cost spike.

1. Contain the key — now

aws iam list-access-keys --user-name ci-deploy
aws iam get-access-key-last-used --access-key-id AKIAEXAMPLEKEY
aws iam update-access-key --user-name ci-deploy --access-key-id AKIAEXAMPLEKEY --status Inactive

Deactivate first (reversible), delete later after the investigation. If you don't know which user owns a key:

aws sts get-access-key-info --access-key-id AKIAEXAMPLEKEY     # returns the account ID

2. Kill sessions the attacker already has

Temporary credentials obtained with the key (via sts:AssumeRole or GetSessionToken) stay valid after you deactivate it. For each role the user could assume, revoke sessions issued before now:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Deny",
    "Action": "*",
    "Resource": "*",
    "Condition": { "DateLessThan": { "aws:TokenIssueTime": "2026-10-24T09:30:00Z" } }
  }]
}
aws iam put-role-policy --role-name deploy-role --policy-name AWSRevokeOlderSessions --policy-document file://revoke.json

The console's Revoke active sessions button on a role does the same thing.

3. Investigate with CloudTrail

aws cloudtrail lookup-events --lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIAEXAMPLEKEY \
  --start-time 2026-10-17 --max-results 50 \
  --query "Events[].{t:EventTime, e:EventName, src:EventSource}" --output table

lookup-events covers management events in one region for 90 days. Run it in every region, or query a CloudTrail Lake / Athena table over your organisation trail:

SELECT eventtime, awsregion, eventname, sourceipaddress, errorcode
FROM cloudtrail_logs
WHERE useridentity.accesskeyid = 'AKIAEXAMPLEKEY'
ORDER BY eventtime;

Look for: CreateUser, CreateAccessKey, AttachUserPolicy, CreateLoginProfile (persistence), RunInstances in odd regions, PutBucketPolicy, GetObject bursts (data theft), DeleteTrail / StopLogging (covering tracks).

4. Remove what they created

Found Action
New IAM users, keys, login profiles Delete after capturing details
Policies attached to existing principals Detach
EC2 instances, Lambda functions, GPU fleets Snapshot if needed for forensics, then terminate
Changed bucket policies or public ACLs Revert; turn on Block Public Access
Disabled CloudTrail or GuardDuty Re-enable immediately

5. Recover and rotate

  • Issue a replacement for the legitimate workload — ideally not a key (see below).
  • Delete the compromised key: aws iam delete-access-key --user-name ci-deploy --access-key-id AKIAEXAMPLEKEY.
  • If data was accessed, involve your security, legal and privacy teams.

Prevent it next time

  • Replace IAM user keys with roles: IAM Identity Center for people, OIDC federation for CI (GitHub Actions, GitLab), instance profiles and IRSA/EKS Pod Identity for workloads.
  • Turn on GuardDuty in every region and account, with findings routed to on-call.
  • Secret scanning on repositories and container images.
  • An SCP that denies iam:CreateAccessKey except for a break-glass role.