A developer accidentally pushed their AWS root account Access Keys to a public GitHub repository. What is your immediate incident response sequence?
Quick Answer
First, deactivate or delete the exposed root access keys immediately via the AWS Console or a break-glass alternate credential, since root keys grant unrestricted account access and every second they remain valid is active exposure — do this before even removing the commit from GitHub, because GitHub history and forks can preserve the secret indefinitely regardless of a force-push. Then rotate every other credential that could have been derived or accessed using root (IAM users, access keys, other secrets stored in the account), audit CloudTrail for any API activity from the exposed key during its exposure window, and only after containment is confirmed do you deal with scrubbing the Git history.
Detailed Answer
Think of this like discovering your house master key is taped to a flyer stapled to a public bulletin board. Your first move isn't to carefully peel the flyer off the board — by the time you're doing that, anyone walking by could have already photographed it, and photographs don't come off the board when you remove the original. Your first move is to change the locks. Everything else — figuring out who saw it, cleaning up the bulletin board — happens after the locks are changed, because that's the only action that actually stops ongoing risk.
AWS designed root account credentials to have complete, unrestricted control over the account with no permission boundary possible — unlike IAM users, root cannot be constrained by an SCP, permission boundary, or resource policy in most cases, which is exactly why AWS's own best practice is to avoid creating root access keys at all and use IAM users or roles for everyday operations. Once root keys are public, the account is compromised in the fullest sense: an attacker could create new IAM users, delete CloudTrail logging, spin up expensive compute in unused regions for cryptomining, or exfiltrate data from every service in the account, all with zero permission checks standing in the way.
Internally, the response needs to happen in strict priority order because each step closes a different door. Deactivating the key (or deleting it and creating a new one, then deactivating the exposed one immediately) via the IAM console under 'My Security Credentials' takes effect within seconds and is the single action that stops any further API calls with that credential — this must happen before anything else, including notifying anyone or investigating scope, because scope investigation doesn't reduce ongoing risk and every minute of delay is a minute of continued exposure. Once the immediate bleeding is stopped, CloudTrail (assuming it wasn't disabled by an attacker, which is itself something to check) provides an audit trail of exactly which API calls were made with the exposed key, letting you distinguish 'exposed for 6 minutes with zero suspicious calls' from 'exposed for 6 minutes with a new IAM user created and attached to AdministratorAccess,' which are two very different incidents requiring very different follow-up.
At production scale, mature incident response here also includes checking AWS Config history and CloudTrail for any new IAM users, roles, or access keys created during the exposure window (since an attacker's first move is usually to create a persistent backdoor credential before the original one gets revoked), reviewing billing alerts and Cost Explorer for anomalous spend in unused regions (a classic sign of cryptomining), and rotating not just root but every other secret potentially reachable from root-level access, since root can read Secrets Manager, Parameter Store, and any KMS-encrypted data in the account. AWS's own Trusted Advisor and GuardDuty often flag exposed credentials automatically within minutes of a public GitHub push, since AWS actively scans public repos for leaked key patterns and may auto-quarantine the key by attaching a deny-all policy — treating this proactive AWS notification as confirmation, not as the primary detection mechanism, is a key operational maturity signal.
The non-obvious gotcha: git commit --amend or a force-push to remove the secret from the latest commit does not remove it from GitHub's history, cached forks, or any CI system that already cloned the repo and may have cached the .git objects — the secret must be treated as permanently public the moment it's pushed, and the entire remediation strategy should assume it has already been scraped by an automated bot, since these exist specifically to harvest credentials from public commits within seconds of a push, often faster than a human notices the mistake.