Why Your AWS IAM Policies Are Probably Broken (And You Don’t Know It Yet)

I’ve audited IAM policies across dozens of organizations. The pattern is always the same: teams ship overpermissioned policies because they don’t realize what they actually wrote. (skip the huddle go and visualize policies using iam policy visualizer)

This isn’t a judgment. It’s a numbers game. AWS IAM policy syntax is verbose and nested. Most policies aren’t read after they’re written—they’re deployed and forgotten. When was the last time someone on your team sat down and genuinely understood what s3:Get* actually grants? Or what wildcard actions really do in a bucket policy versus an identity policy?

The Usual Suspects

The mistakes I see constantly:

1. The Copy-Paste Disaster

Someone finds a policy on Stack Overflow or in old documentation, copies it, tweaks two lines, and ships it. This pattern is especially dangerous with S3 bucket policies, where the mechanics work differently than identity-based policies. The original policy probably had overly broad permissions because the author was frustrated with debugging access denied errors. Now that permission pattern propagates across your infrastructure.

I once found a policy that granted dynamodb:* on all tables because a junior engineer got tired of playing access denied whack-a-mole during development. Three years later, it was still in production on a service that only needed to read one specific table.

2. The “Just Use Wildcard” Approach

When debugging access issues, the path of least resistance is widening permissions until it works. A developer runs into a 403, doesn’t have time to figure out which specific action they need, so they go from s3:GetObject to s3:*. Then they move on. The policy never gets fixed because the problem appears solved.

3. The Resource Scope Mistake

People often nail the action (what you can do) but fail on the resource (what you can do it to). You see policies that correctly restrict to s3:GetObject but then use a resource of arn:aws:s3:::*. Now any principal with that policy can read any object in any bucket in the account. That’s not least privilege; that’s “least effort.”

4. The Trust Relationship Blindspot

Trust relationships (assume role policies) get even less attention than inline policies. Teams set them up to “make it work” and never revisit them. I’ve seen service roles with trust relationships that allow any principal in the account to assume them. The principal itself is restricted, but the trust policy is written like it’s for a public resource.

Why This Matters Now

For years, this was the “not a real problem” problem. Permissions were loose, but nobody publicly exploited them. Internal threats were rare. Compliance was handled by saying “we use IAM.”

Then:

  • Ransomware became AWS-aware. Attackers who compromise one application now enumerate IAM permissions and move laterally.
  • Compliance got teeth. SOC 2 audits now include actual policy reviews, not just “do you have IAM?”
  • Your blast radius grew. Your infrastructure is bigger than it used to be. One over permissioned role now affects more systems. S3 is where this shows up most—one overpermissioned bucket policy can expose your entire data lake, which is why engineers keep getting S3 policies wrong.
  • Your team is more distributed. Fewer people understand what policies actually do. The original author left. Documentation doesn’t exist.

The Real Problem Isn’t Policy Syntax

It’s that IAM policies are written in a format humans are bad at reasoning about.

JSON is a data format, not a policy language. It’s machine-readable but not human-readable in the way we actually need. When you glance at a policy, your brain doesn’t automatically compute “this grants delete access to everything.” You have to mentally parse nested objects, remember what specific action names actually do, and map those to real-world permissions.

This is why people find JSON policies hard to verify. It’s not stupidity. It’s cognitive load. Your brain just isn’t wired to read a 50-line JSON document and confidently say “yes, this is exactly what I meant.”

Try it yourself. Someone hands you a policy they wrote. Really understand it in 30 seconds. Understand all the edge cases. What can someone with this policy actually do? What about future S3 bucket actions that haven’t been invented yet? What if a new resource is added that matches the wildcards?

Most people can’t do it. Most people shouldn’t have to.

What Actually Fixes This

The fix isn’t stricter rules or more process. People follow process until they’re under deadline pressure, then they skip it.

The fix is making it easy to verify what you actually wrote. If you paste a policy into a tool and it tells you in plain English what it grants—with warnings where you’ve widened permissions—you catch mistakes before deployment.

You also don’t have to reverse-engineer policies someone else wrote. You read a generated English explanation instead of parsing JSON. This is why an IAM policy visualizer changes the game. Instead of squinting at JSON, you get human-readable output: “⚠️ This policy allows ANYONE to delete your database.” You see the problem immediately. No parsing required.

Templates help too. The number one reason people write overpermissioned policies is they have to write them from scratch. If you can select “read-only access to specific S3 bucket” from a template, you’re starting from a safe baseline instead of guessing. A solid IAM policy generator with real templates (not just documentation links) removes the “write from scratch” friction that causes people to take shortcuts in the first place.

The Uncomfortable Truth

If you haven’t audited your IAM policies in the last two years, you’re probably running something that violates least privilege. Not because your team is negligent, but because IAM policy review isn’t automated, and reviewing them manually is tedious.

The policies that are actually dangerous aren’t the obviously bad ones—those get caught eventually. They’re the ones that seem okay because nobody looked at them closely enough. They’re the ones that give way more than they need to, but not SO much that anyone notices.

Until something goes wrong.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top