Every AWS account starts clean. Someone sets up a few IAM users, maybe a role or two, and everything makes sense. Eighteen months later, that same account has forty IAM users, a dozen roles nobody can explain, and at least one policy with a wildcard resource that grants far more access than anyone intended.
This isn't negligence. It's what happens when a team is moving fast and IAM cleanup never makes it to the top of anyone's list. Here's the pattern we see most often, and where to start.
The sprawl pattern
IAM sprawl tends to follow the same lifecycle in almost every account we look at:
- A contractor or agency gets access to ship something quickly, and the access outlives the project.
- A policy gets written with a wildcard because narrowing it down would have taken longer, and there was a deadline.
- A service account gets admin access during initial setup, "just to get it working," and nobody comes back to scope it down.
- An employee changes teams or leaves, and their access gets forgotten instead of revoked.
None of these decisions were unreasonable in the moment. The problem is that they compound, and nobody owns going back to clean them up until something forces the issue, like a SOC 2 audit or an incident.
Where to actually start
Trying to fix everything at once usually stalls out. A more realistic approach is to work through it in order of risk.
1. Find unused credentials first
AWS's IAM credential report shows the last time every access key and password was used. Anything untouched for 90 days or more is a strong candidate for removal. This is the lowest-risk cleanup step because if nobody's used it in three months, removing it is unlikely to break anything.
2. Look for wildcard actions and resources
Search your policies for "Action": "*" or "Resource": "*". Each one is worth a second look. Some are genuinely necessary for a small number of admin roles. Most are there because scoping the policy down correctly took more time than anyone had.
3. Separate human users from service accounts
If a person and an automated process are using the same IAM user, you can't tell which one did what when something goes wrong. Give every service and every automated pipeline its own role, and keep human access tied to individual named users.
4. Move toward roles instead of long-lived keys
Long-lived access keys are one of the most common things we find exposed in old scripts, CI configs, and even public GitHub repos. Where possible, use IAM roles with temporary credentials instead of static keys that don't expire on their own.
Why this matters beyond "best practice"
IAM sprawl is not just a theoretical risk. It's one of the first things an auditor checks during SOC 2 prep, one of the first things an enterprise customer's security team asks about, and one of the first things that turns a small mistake into a large incident when a single compromised credential has far more reach than it should.
Want to check your own account first? The IAM section is part of the 10-point AWS baseline checklist we run on every sprint.
Get the ChecklistIf your IAM setup has grown well past what anyone can explain from memory, that's exactly the kind of gap the AWS Startup Security Baseline sprint is built to close, with a live working session where we go through the cleanup together instead of just handing you a list of problems.