Skip to content

Identity & access

Over-privileged roles & policies

Over-privileged roles are the quiet default of every cloud estate: permissions are easy to add and almost never removed, so identities accumulate access the way a garage accumulates boxes. A role created to "just make the deploy work" gets AdministratorAccess on a Friday and keeps it for three years; a service account for a single Lambda ends up able to read every bucket and assume every role in the account. This sub-topic is specifically about the gap between what an identity can do and what it actually needs — the effective, resolved permission set after managed policies, inline policies, group memberships, resource policies, and permission boundaries are all evaluated together. We measure that gap for human users, service accounts, roles, and application identities alike, and we pay special attention to the permissions that let one identity become another (privilege-escalation paths), because those turn a modest grant into full control.

Overview

What this check looks like in practice

Roles and policies drift toward “just make it work,” accumulating permissions nobody audits. Wildcards (*:*), broad managed-admin policies, and unused grants widen the blast radius of any compromise. We measure the gap between what identities can do and what they actually use.

Employee badge being scanned at a modern office lobby access reader for workplace identity and access control
Identity & access

Why it matters

Access is the whole game in the cloud, and over-privilege is what decides the blast radius when — not if — a credential is exposed. A phished session, a token leaked in a build log, or a compromised third-party integration is a contained incident if the identity is tightly scoped, and a full-account takeover if it holds wildcard or admin-equivalent rights. Attackers rarely need an exploit when a single iam:PassRole plus lambda:CreateFunction, or a role that can attach its own policies, hands them administrator by design. Auditors read the same signals in reverse: standing admin, unused broad grants, and unbounded roles are exactly what SOC 2, PCI-DSS Requirement 7, and the CIS IAM benchmarks flag as least-privilege failures, so a finding here and an audit exception are the same sentence. Because over-privilege stays invisible until it is exploited, closing the gap is the highest-leverage, lowest-disruption hardening most organizations can do.

What we assess

What we look for

  • Wildcards in policy statements — Action "*", Resource "*", or service-level "s3:*" grants — and attachment of admin-equivalent managed policies (AdministratorAccess, Owner, roles/owner)
  • The gap between granted and used permissions: entitlements that have never been exercised in the available access-history window and can be removed with no functional impact
  • Privilege-escalation paths — identities that can pass roles, create or update policies, attach policies to themselves, create access keys for others, or spin up compute that assumes a more powerful role
  • Human users carrying standing administrative access instead of time-bound, just-in-time elevation with approval and expiry
  • Service accounts, machine roles, and application identities scoped far wider than the single workload they serve, including reuse of one powerful identity across many workloads
  • Absence of guardrails that cap effective permissions — AWS permission boundaries and SCPs, Azure custom-role scoping and management-group RBAC, GCP org-policy constraints and deny policies
  • Broad grants applied at the account, subscription, or organization/folder level that should be scoped to a single project, resource group, or resource
  • Custom roles and inline policies that quietly re-grant sensitive actions the managed baseline was chosen to avoid

Across your clouds

AWS, Azure & Google Cloud

AWS

We resolve effective permissions across IAM users, groups, roles, inline and managed policies, and SCPs, then use IAM Access Analyzer (including unused-access findings and policy generation from CloudTrail) and Access Advisor last-accessed data to separate used from unused grants. We flag AdministratorAccess and wildcard statements, missing permission boundaries on roles that can create identities, and classic escalation combos like iam:PassRole with compute-create or policy-write actions.

Azure

We review Azure RBAC role assignments and scope across management groups, subscriptions, and resource groups, flagging Owner/Contributor and broad built-in roles where a tightly scoped custom role would do. We check for standing privileged assignments that should move to Entra ID PIM (just-in-time, time-bound, approval-gated), over-privileged managed identities and service principals, and app registrations holding high-risk Graph or directory permissions.

Google Cloud

We evaluate Cloud IAM bindings across the organization, folder, project, and resource hierarchy, using Policy Analyzer and the IAM Recommender to surface unused and over-broad grants. We flag primitive roles (Owner/Editor/Viewer) in place of predefined or custom roles, service accounts with excessive project- or org-level roles, and escalation-enabling permissions such as iam.serviceAccounts.actAs, setIamPolicy, and service-account key or token creation.

Example finding

An application role that can escalate to administrator via iam:PassRole and lambda:CreateFunction

Risk: The role was scoped for a data-processing job but retains iam:PassRole (Resource "*") together with lambda:CreateFunction and lambda:InvokeFunction. Anyone who obtains this identity can create a function, pass it a far more privileged existing role, and invoke it to execute as that role — reaching administrator without ever touching an admin policy directly. It is a full escalation path hiding inside a permission set that looks purpose-built.

Fix: Constrain iam:PassRole to the specific role ARNs the workload legitimately passes and add an iam:PassedToService condition; remove Lambda-management actions the job does not use; and apply a permission boundary so the role can never grant itself or others more than its intended ceiling. Re-derive the policy from observed CloudTrail activity so the result matches real usage rather than the original over-broad guess.

Remediation

How to close it

  1. 1 Build an effective-permissions baseline: resolve each identity's real access across managed/inline policies, group and role memberships, resource policies, and boundaries — not just what is attached in isolation.
  2. 2 Rank by blast radius, not by count: fix identities that combine broad reach with escalation paths or production access first, and treat wildcard/admin-equivalent grants on machine identities as top priority.
  3. 3 Right-size from evidence: use last-accessed and access-history data (Access Analyzer/Access Advisor, Policy Analyzer/Recommender, Entra sign-in and PIM data) to strip unused permissions and regenerate least-privilege policies from actual activity.
  4. 4 Convert standing admin to just-in-time elevation: move human privileged access to time-bound, approval-gated grants (Entra PIM or equivalent) so no one carries administrator by default.
  5. 5 Install guardrails that cap effective permission: permission boundaries and SCPs on AWS, management-group RBAC and custom roles on Azure, org-policy constraints and deny policies on GCP — so future drift cannot exceed the ceiling.
  6. 6 Prevent regression: require least-privilege review in IaC/policy pipelines, alert on new wildcard or admin grants, and schedule periodic unused-access re-checks so entitlements shrink over time instead of only growing.

Questions

How do you know a permission is actually unused and safe to remove?

We rely on provider access-history evidence — AWS IAM Access Analyzer unused-access findings and Access Advisor last-accessed data, GCP's IAM Recommender and Policy Analyzer, and Azure sign-in and PIM activity — rather than guessing. That shows which granted actions have not been exercised in the available lookback window. We present it as ranked, reversible recommendations with the supporting evidence; you decide and apply the change, since the assessment is read-only and never modifies a policy itself.

Why focus on escalation paths instead of just counting broad policies?

Because permission count is a poor proxy for risk. A role with one seemingly narrow permission — iam:PassRole, setIamPolicy, or the ability to attach a policy to itself — can be a direct route to administrator, while a role with many read-only actions may be harmless. We trace which identities can become more powerful identities, because that is what turns a modest compromise into a full-account one, and it is exactly what a raw permissions dump hides.

Isn't least privilege going to break our applications?

Done blindly, over-tightening breaks things — which is why we right-size from observed usage rather than from assumptions. Policies regenerated from real activity keep what the workload actually calls and drop what it never touches, and permission boundaries cap the ceiling without removing day-to-day function. We also sequence changes so high-risk standing admin and escalation paths are addressed before low-risk cleanup, giving you a safe order to roll out.

See where you stand

A health check finds and prioritizes real exposure. It is not a certification or a promise you will never be breached — closing the findings is what changes your risk.

Related domain surfaces

The rest of what we assess

The same read-only assessment covers every domain — see what else it looks at.