Most cloud breaches do not need a zero-day. They need a credential, and then the permissions attached to it. An attacker who gets code running in a container inherits whatever role that container runs as, and from that moment the question is no longer “how did they get in?” but “what could that role do?”. In most AWS accounts, the honest answer for a surprising number of roles is “more or less anything”.

This post follows one illustrative role, payments-api-task in the demo account acme-prod (demo), from discovery to a least-privilege policy, and shows how to find the others like it.

In short

  • Effective permissions are the union of many policies. Managed, inline and group policies, each reasonable alone, add up to roles that are administrators in all but name.
  • Look for escalation, not just administrator. A role that can attach a policy to itself or pass a privileged role to new compute can become an administrator in one call.
  • Measure blast radius against what matters. Which sensitive resources can this identity read or change? That is the risk statement the business understands.
  • Shrink from evidence. Access-advisor data shows which services a role actually used; a policy limited to those is a safe starting point for least privilege.

Why over-privilege is the default

No one sets out to create an administrator role for a payments API. It happens in steps. A developer needs the service to read one bucket and attaches AmazonS3FullAccess because the deadline is tomorrow. A later feature needs to send messages and someone adds an inline policy with sqs:*. A shared group policy grants iam:PassRole for a deployment script. Each change was reviewed, or at least approved, in isolation. Nobody reviewed the sum.

Industry
data

Cloud security research from several major providers has repeatedly found that the large majority of granted cloud permissions are never used, and that valid credentials, rather than software exploits, are among the most common ways attackers operate in cloud environments.

Sources: Microsoft State of Cloud Permissions Risks report (2023); Verizon Data Breach Investigations Report (credential abuse); public cloud incident analyses. Exact percentages vary by study.

POLICY BY POLICY Review each policy as it is written

A pull request adds one statement and looks reasonable. The role’s effective permissions, across every attached policy, are never computed or reviewed.

IDENTITY BY IDENTITY Compute effective permissions per identity

Every managed, inline and group policy is folded into one list of allowed actions and resources for each user and role, then checked for administrator access, escalation paths, open trust and unused grants.

What the analysis looks for

InsightFortify’s AWS identity analysis works from one export, aws iam get-account-authorization-details, which lists every user, group and role and every version of every policy. It is collected by the read-only scan role or uploaded. For each principal it folds the default version of every attached managed policy, every inline policy and, for users, every group’s policies, then flags:

CheckWhat it meansWhy it matters
Full administratorAction: * on Resource: *, or AdministratorAccessA compromise of this identity is a compromise of the account
Privilege escalationHolds a known route to more power, such as iam:CreatePolicyVersion, iam:Attach*Policy, iam:PassRole with a compute service, rewriting a trust policyNot an administrator today, one API call from being one
Open trustA role anyone can assume, or another account can assume without an ExternalId conditionThe confused-deputy problem: someone else’s compromise becomes yours
UnusedNever used, or not in 90 days, but still holds permissionsStanding access with no business need
Broad wildcardsservice:* on every resourceOver-grant that is usually accidental and easy to narrow

The escalation catalogue follows published research on AWS privilege escalation, notably Rhino Security Labs’ work, and each path found is named in plain language: “Pass a privileged role to a new Lambda and invoke it”, rather than a list of action strings.

A limitation stated up front

The analysis reports what policies grant. It does not subtract explicit denies, permission boundaries or service control policies. For a principal that an SCP or boundary already limits, it can over-report. That is the safer direction to be wrong in, but you should know it. Identity analysis currently covers AWS; Azure and Google Cloud posture checks run through Prowler, without this entitlement analysis.

Blast radius: from permissions to business impact

A list of 300 allowed actions does not tell an executive anything. “This role can read the bucket of card-payment exports” does. Blast radius is computed by matching an identity’s effective grants against the resources the posture scan has inventoried, with special attention to the ones you have marked as holding sensitive data. Marking a resource sensitive is a one-click decision on the cloud account page, and every finding and attack path re-evaluates when you do.

The identity page for payments-api-task: on one attack path, blast radius reaching the sensitive and public acme-payments-exports bucket, and a least-privilege starting point
The identity page. payments-api-task is on an attack path, its blast radius reaches the sensitive acme-payments-exports bucket, and access-advisor data shows it only ever used S3.

In the demo account, payments-api-task is assumable by the ECS tasks service and holds s3:* through a policy simply called “data”. Its blast radius includes acme-payments-exports, a bucket marked sensitive and also public. Because the payments service faces the internet and its image has exploitable vulnerabilities, the role sits on an attack path, and the page says so at the top.

flowchart LR A["IAM export
users, groups, roles, policies"] --> B["Fold effective
permissions per identity"] B --> C{"Admin, escalation,
open trust, unused?"} C -->|"yes"| D["Identity finding"] B --> E["Match grants to
inventoried resources"] S["Resources marked sensitive"] --> E E --> F["Blast radius"] F --> G["Attack paths
exposed workload runs as it"] H["Access advisor
services used"] --> I["Least-privilege
starting policy"]

Least privilege from what was actually used

The reason least privilege projects stall is fear: nobody wants to remove a permission and break production at 2am. The evidence that removes the fear exists. AWS access-advisor data records which services each role has used. When that data is included in the export, each identity gets a recommended policy limited to the services it used. For payments-api-task, that is S3 only.

It is a starting point, not a finished policy. Service-level scoping is coarser than action-level or resource-level scoping, and the next step, limiting s3:* to s3:GetObject on the one bucket the service reads, needs someone who knows the application. But it turns a frightening blank page into a reviewable diff.

sequenceDiagram participant C as Cloud security participant F as InsightFortify participant A as AWS account - read-only role participant T as Payments team participant P as Platform - IaC C->>F: Scan acme-prod F->>A: Export IAM details and access advisor A-->>F: Users, roles, policies, services used F->>F: Fold permissions, find escalation F->>F: Blast radius reaches sensitive bucket F-->>C: Identity and path findings, P1 C->>T: Proposed policy - S3 only, one bucket T-->>C: Confirms reads, adds one write prefix T->>P: Pull request to the role in Terraform P->>A: Apply narrowed policy C->>F: Rescan F-->>C: Path closed, finding fixed

Illustrative. The fix happens in your infrastructure-as-code; InsightFortify proposes and verifies, it does not change IAM.

Shrinking an over-privileged workload roleIllustrative runbook with typical owners
1
Run the identity analysisCloud security

Scan the account through the read-only role, or upload the IAM export with access-advisor data.

2
Sort by power, then by blast radiusCloud security

Administrators and roles that can escalate first; among those, the ones reaching sensitive resources or sitting on attack paths.

3
Agree the intended access with the ownerService team

Start from the recommended policy. Name the actions and the specific resources the service needs.

4
Change it in codePlatform

Update the role in Terraform or CloudFormation; the IaC scan checks the change at the pull request.

5
Apply and watchPlatform + service team

Deploy in a lower environment first; watch for access-denied errors for a release cycle.

6
Rescan and confirmCloud security

Escalation and admin findings close; the attack path closes because a link is gone.

7
Remove unused identitiesCloud security + owners

Roles unused for 90 days: disable, wait, delete.

What changes for each audience

For the CISO

Identity risk is expressed in terms that survive a board conversation: which roles can reach which sensitive data, and how many can make themselves administrators.

Least privilege becomes a measurable programme with a burn-down, not a principle in a policy document.

For the AppSec lead

Every finding names the escalation path in plain language and comes with a proposed policy, so the conversation with a service team starts from evidence.

Attack paths show which identity changes remove the most risk for the least effort.

For the board

“How many cloud identities could take over an account if compromised?” is a number, it is tracked, and it should fall every quarter.

It is directly relevant to the controls regulators and auditors increasingly ask about.

Outcome metrics

MetricDefinitionTarget direction
Effective administratorsIdentities with full admin, by accountSmall, named, justified
Identities that can escalateNon-admins holding an escalation pathDown to zero outside break-glass
Identities reaching sensitive dataBlast radius includes a resource marked sensitiveOnly those whose job needs it
Unused identitiesNo use in 90 days, permissions still attachedDown, continuously
Attack paths through an identityOpen path findings whose identity link is this roleZero

Attackers do not need to break in if they can log in. They then need only what the identity already allows.

Compute what every identity can really do, measure it against the data that matters, and narrow it from evidence of what it actually used.

Keep reading