A policy review usually fails in a quiet way. Nobody approves a statement that says "give this role everything", but plenty of reviewers approve a statement that looks small, uses a familiar action name, or is shorter than the policy it replaces. The result is a policy that passes the glance test and still lets a holder do much more than its job requires. This guide walks through five kinds of grant in AWS Identity and Access Management that get through review again and again: broad star grants, passing any role, an allow with an exclusion list, a public principal without limits, and actions that let the holder change its own rights. For each one it says what to look for, what the narrow version looks like, and which look-alikes are fine.

The standard you are reviewing against

AWS describes the target plainly: grant only the permissions needed for a task, by naming actions, specific resources and conditions, which it calls least privilege. It also admits that teams may begin with broad permissions while they find out what a workload needs, and then tighten them as the use case matures (AWS, security best practices). That second sentence is the honest source of most wide policies: the broad version was meant to be temporary, and review is the moment it either gets narrowed or becomes permanent.

So the review question is never "is this policy valid?" It is "could the same job be done with less?" The five patterns below are the places where the answer is most often yes.

Pattern one: star on star, or a full service across everything

The obvious form is an allow that puts a star in the action slot and another in the resource slot. Reviewers catch that. The form that gets through is one step softer: every action of a single service, such as sqs:* or s3:*, aimed at a bare star. It reads like a scoped grant because it names one service, yet it still covers every action of that service against everything in the account.

What to check: read the action and the target of each allow together. Everything-in-one-service is tolerable when the target is a single bucket, a single table or a clearly prefixed set of names, while an unrestricted star makes it a finding. The cure is to enumerate the few calls the job really makes and to name what they touch.

Pattern two: lending a service whichever role it asks for

Many AWS services work by taking a role from you and acting with it later. To hand a role to a service, the caller needs the iam:PassRole permission. AWS explains the purpose: it lets administrators make sure only approved people can configure a service with a role that carries permissions (AWS, passing a role to a service).

The danger is in what the role can do, not in what the caller can do. The same page gives the example of a person who has no Amazon S3 access of their own but can pass a role that allows S3 to a service; the service then performs the S3 actions while running their job. If the permission is allowed on a star resource, or on a wildcard that matches every role, the caller can pick the most powerful role in the account and borrow it.

What to check: the target of every statement that allows iam:PassRole. AWS says the permission can be narrowed through the resource element so that only approved roles can be passed, and further with the iam:PassedToService condition key, which names the service that may receive the role. The narrow version names the one role the job needs, or a prefix shared by the few roles it needs. An unrestricted star is the finding.

Pattern three: Allow with NotAction

An allow statement with NotAction reads backwards, and that is why it passes. Instead of listing what is permitted, it lists what is left out, and everything else is permitted. AWS states that the actions named in NotAction are not affected by the allow or deny effect, so with an allow, every action or service not listed ends up allowed. It gives an example that permits every action in every service except those of IAM, and it warns that this matches everything not explicitly listed and so may give out more than you meant (AWS, NotAction).

The shortness is the attraction: one excluded action in place of a long list. The cost follows from the definition: anything not listed matches, so an action added to a service later is allowed too, without anyone editing the policy.

What to check: any allow statement that contains NotAction. Combined with a resource that limits the scope to one service's objects it is less open, but the safe fix is still to list the allowed actions.

A look-alike that is fine here: a deny statement with NotAction. AWS describes it as denying everything except the listed actions, and it still requires you to allow what you want separately. It is a frequent shape for a guardrail, such as "deny everything unless the person signed in with a second factor", and it narrows access instead of widening it.

Pattern four: a public principal with nothing limiting it

In a resource policy, such as a bucket policy, the principal says who is being granted access. A star there means everyone. AWS says it strongly recommends against a star principal with an allow effect unless public or anonymous access is the intent, and that a star with an allow grants access to all users, anonymous ones included. For anonymous users the two spellings, a bare star and the AWS key set to star, are equivalent (AWS, the Principal element).

Reviewers miss it when the statement has a condition, because a condition looks like a limit. It depends on what the condition tests. A test on which organization the caller belongs to, or on the path the request travels, does restrict who can call. A condition that only demands an encrypted connection does not restrict who can call, since anyone can use an encrypted connection.

What to check: every resource-policy allow with a star principal. Ask what, exactly, narrows the set of callers. If the answer is nothing, or only transport security, the bucket is public.

Pattern five: actions that let the holder widen its own access

The last group is the least visible because none of the actions touches your data. They change the policies themselves. iam:CreatePolicyVersion creates a new version of a managed policy, and the API reference notes that the default version is the one in effect for every user, group and role the policy is attached to (AWS, CreatePolicyVersion). Someone who may create a version of a policy attached to their own role can write a more generous version and make it the default. Likewise, actions that bind a managed policy to a person, or put an inline policy on one, let the holder grant rights to themselves or to a colleague, and the same applies to the equivalent actions for roles and groups.

What to check: these actions paired with an unrestricted target. Pointed at one named target they are a smaller concern. They belong with the few people who administer access, never with an application role.

A review order that works

When you read an unfamiliar policy, go statement by statement and write down, for each allow, five answers: is any action a service-wide star, is a role being passed and how widely, does it use NotAction, is the principal public and what limits it, and can it change policies. Then compare the answers with the job the policy is for. A deny statement needs a different reading, because it removes access rather than adding it.

Keep the review confined to the document in front of you. A permissions boundary, an organization-level policy or another policy attached to the same identity may narrow things further, and you cannot see them from one file. Say that, rather than guessing in either direction.

When this does not apply

Only AWS identity policies and resource policies in JSON form are covered. Other clouds use different policy languages and are out of scope. Five patterns are not a complete list of risky grants: a narrow-looking action can still be dangerous in combination with another, and a policy can pass all five checks and still be wider than the job. Permissions boundaries, service control policies at the organization level, session policies and role trust policies can all change the real effect, and none of them appears in a single policy file. Nothing here comes from a fresh experiment of ours: the text follows AWS documentation plus ordinary review practice, so read the examples as illustrations. AWS pages change, so confirm details on the pages cited.

Handing out access you cannot see the limits of has the same shape as running outside code you have not read, a risk we discuss from the supply side in our write-up on trusting third-party skills.

A tool for the pre-attach read

Our iam-policy-review skill takes one IAM or bucket policy and reports only the five grant types above. Each finding is a line carrying a short code, the statement concerned, the risk and the repair. A clean policy gets a plain "No findings". Harmless relatives, for instance read access to one bucket or a public principal tied to an organization, stay unreported, and text inside the policy that calls a grant safe is ignored as data.

Read this post as Markdown: /blog/iam-policy-wide-permissions.md · Atom feed.