Onam
Identity

Why cloud IAM permissions go unused — and why that matters

Every cloud security team has the same conversation at some point: "We have too many IAM policies to audit manually." What they rarely say out loud is that the vast majority of the permissions in those policies have never been used once.

We are not going to put a percentage on it: a figure without a published sample behind it is marketing, not data. What is consistent is the mechanism. Permissions are granted to make something work and almost never removed when the thing stops needing them. It is not a failure of individual teams — it is the natural consequence of how cloud IAM actually works in practice.

Illustrative IAM Security view — stylised, with demo data
Illustrative IAM Security view — stylised, with demo data

How permissions accumulate

Cloud IAM permissions grow through three mechanisms, none of which are intentionally malicious.

Copy-paste onboarding. When a new service account or role is needed quickly, engineers copy an existing role and modify it. The source role has permissions that were useful once — a temporary migration, a debugging session, a feature that was later removed. Those permissions carry forward into every derivative role.

Managed policy breadth. AWS managed policies like AmazonS3FullAccess and AmazonEC2FullAccess cover entire service surfaces. A Lambda function that only reads from one S3 bucket gets full S3 permissions because attaching a managed policy is three clicks and writing a custom policy is forty minutes. The path of least resistance is also the path of least privilege violation.

Permission creep without cleanup. Role permissions accumulate as features get added. Nobody removes permissions when features are deprecated. A role that started with five specific permissions in 2022 has thirty by 2026, and the engineers who added the original five have moved to other teams.

Why unused permissions matter

An unused permission is not harmless. It is a door that does not need to exist. From an attacker's perspective, the difference between a compromised Lambda execution role that can only read from one S3 bucket and one that has full S3 access is the difference between a minor incident and a data breach.

Consider the MITRE ATT&CK technique T1078.004 (Valid Cloud Accounts). When an attacker compromises a service account — through a misconfigured endpoint, a leaked credential in source code, or a supply chain attack — they inherit exactly the permissions that account holds. If that account has permissions it never uses, the attacker has capabilities the account's legitimate owners never intended to grant.

The SolarWinds attack demonstrated this at scale: compromised service accounts with broad cloud permissions allowed lateral movement that would have been impossible with properly scoped access. Every permission that exists but is not needed is a pivot point that should not exist.

How CIEM measures the gap

CIEM (Cloud Infrastructure Entitlement Management) addresses this by computing the least-privilege gap — the difference between what an identity is permitted to do and what it actually does. Here is how Onam does it today.

1. Effective permission resolution. Attached policies alone do not tell you what a principal can actually do. Group membership adds permissions; explicit denies elsewhere remove them; conditions decide whether a grant applies at all; Service Control Policies (SCPs) at the organization level can block what an identity policy allows. Onam copies group policies onto members, classifies every condition by whether an attacker could satisfy it, nets out explicit denies and checks SCP deny statements. Permission boundaries and resource-based policies add further layers that Onam does not yet fold into the result — the docs list exactly what is and is not modelled.

How Onam resolves effective permissions on AWS — statements, groups, conditions, denies and SCPs
How Onam resolves effective permissions on AWS — statements, groups, conditions, denies and SCPs

2. Usage analysis from activity logs. CloudTrail records the API calls made in your AWS account. Onam reads the CloudTrail events its threat detection collects and builds a map of which actions each identity called. A granted action that has not appeared in the activity window is counted as unused, and the high-risk ones — iam:PassRole, iam:CreatePolicyVersion, s3:PutBucketPolicy, kms:ScheduleKeyDeletion and similar — are listed separately. Onam does this for AWS today.

3. A concrete change, not an abstract one. The unused list — especially the high-risk unused actions — tells engineers exactly what to remove, and the used list is the starting point for a replacement policy. That is a change someone can review, rather than a vague "reduce permissions" ticket.

Where the gap is usually widest

Some identity types accumulate unused permissions faster than others:

  • Service accounts and workload roles (Lambda, ECS, EC2 instance profiles). Created for one feature, forgotten when the team moves on, and rarely reviewed because no human logs in as them.
  • Cross-account roles. Set up for a partner, a migration or a tool, then left in place long after the reason has gone.
  • Human users. Permissions follow people through team changes; few are removed when they move.
  • Federated identities. Broad SSO roles are convenient and hard to scope per person.

What to do about it

The goal is not to achieve zero unused permissions immediately. That would require rewriting every IAM policy in your account simultaneously, which is operationally infeasible and will break things. Instead:

Start with the highest-risk identities. Shadow admins — identities that can reach admin-level access without holding an admin role — are the highest priority. A service account that can assume a role that can assume another role with iam:* permissions is a three-hop privilege escalation path. CIEM surfaces these chains; fix them first.

Enforce for new identities. The easiest permission to remediate is one that was never granted. Add a review gate to your IAM policy creation process that requires justification for any permission a similar role has not needed. This does not fix existing debt, but it stops new debt from accumulating.

Automate the analysis, not the removal. Let tooling compute the gap continuously, but do not remove permissions automatically — have a human review each change for operational correctness first. What looks unused over a few weeks may be used on a quarterly or annual cycle.

The cost of a false-positive access removal is a production incident. Measure automatically, remove carefully.

Over-provisioning is not a problem you fix in a sprint. It is a long-running hygiene practice, and the right tool makes continuous progress measurable instead of invisible.

See how this looks on your cloud

A live 30-minute walkthrough of Onam against a sample environment that mirrors yours.