AWS IAM Explicit Deny vs Implicit Deny

Package aws-cli/2.37.3
AWS Region ap-south-1 (Mumbai) is used for the service-call examples. IAM is a global service, although authorization is evaluated for each request using its principal, action, resource, and request context
Lab environment Workstation with AWS CLI v2 and configured credentials — AWS CLI tutorial
Install AWS CLI on Ubuntu · Install AWS CLI on Debian
Privilege Account administrator or IAM permissions to create users, policies, and access keys for the lab principals
Scope How AWS IAM explicit deny and implicit deny differ, what each AccessDenied message can reveal, and how to inspect identity-policy evaluation with aws iam simulate-principal-policy. Covers identity-based policies on IAM users. Does not cover every AccessDenied layer — see AccessDenied despite AdministratorAccess for permissions boundaries, SCPs, session policies, and resource policies.
Related guides AWS CLI Tutorial
AccessDenied despite AdministratorAccess
Which credentials AWS CLI is using
AWS S3 Bucket Setup
AWS Tutorial
Short on time?Beta Get the gist of this 10-minute read in seconds, then ask follow-up questions

AWS starts from a default deny. A request is allowed only when the required permissions are granted by the applicable policy layers and no applicable explicit Deny blocks it. The two outcomes beginners see most often in AccessDenied errors are:

  • Implicit deny — no applicable policy grants the required Allow; errors may say because no identity-based policy allows the action
  • Explicit deny — a Deny statement overrides a matching Allow; enhanced errors usually name the policy type and may include the policy ARN

The examples use two IAM users and s3:ListAllMyBuckets so service error text and simulate-principal-policy output show implicitDeny and explicitDeny side by side.


Default deny in AWS IAM

Two terms used throughout this page:

  • Principal — the AWS identity making the request, such as an IAM user or role
  • Identity-based policy — a permissions policy attached to a user, group, or role that defines which AWS actions that identity can perform

IAM policy evaluation is deny-by-default. For the identity-based policy examples in this article, you can use the following simplified model. In real requests, additional policy layers such as permissions boundaries and SCPs may also need to permit the action.

Rule Effect
No matching Allow Request is denied (implicit deny)
At least one matching Allow and no matching Deny Request is allowed
Any matching Deny Request is denied (explicit deny), even if an Allow also matches
        AWS API request
              |
              v
Evaluate applicable policy layers
              |
              v
    Any explicit Deny applies?
        /            \
      yes             no
        |               |
        v               v
explicitDeny    Any Allow matches?
                      /        \
                    yes         no
                    |           |
                    v           v
                  allowed   implicitDeny

Neither outcome is a standalone policy document:

  • Implicit deny — evaluation found no applicable Allow
  • Explicit deny — a Deny statement matched; AWS can point to it in the error or simulator output when enhanced context is available

Implicit deny example

The first lab user has no applicable identity-based Allow for s3:ListAllMyBuckets — neither directly on the user nor through an IAM group. Because no applicable policy allows the action, AWS denies it implicitly. The lab uses access keys for lab-implicit-user with AWS_PROFILE set to that profile.

Confirm the caller first:

bash
aws sts get-caller-identity
output
{
    "UserId": "AIDAU7QAIUYJEXAMPLE",
    "Account": "123456789012",
    "Arn": "arn:aws:iam::123456789012:user/lab-implicit-user"
}

Run the S3 call that should fail while no Allow policy applies:

bash
aws s3api list-buckets
output
aws: [ERROR]: An error occurred (AccessDenied) when calling the ListBuckets operation: User: arn:aws:iam::123456789012:user/lab-implicit-user is not authorized to perform: s3:ListAllMyBuckets because no identity-based policy allows the s3:ListAllMyBuckets action

The phrase because no identity-based policy allows signals implicit deny: AWS evaluated identity-based policies on the user and its groups and found no applicable Allow.

Simulate the same action without running the API call:

bash
aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::123456789012:user/lab-implicit-user \
  --action-names s3:ListAllMyBuckets \
  --resource-arns "*"
output
"EvalDecision": "implicitDeny",
"MatchedStatements": []

MatchedStatements is empty because the simulation did not find a statement that produced an explicit allow or explicit deny for this request.

Fix implicit deny

Attach a policy that grants the missing action. A minimal Allow for listing buckets:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowListBuckets",
      "Effect": "Allow",
      "Action": "s3:ListAllMyBuckets",
      "Resource": "*"
    }
  ]
}

After IAM propagates the attachment, simulation returns allowed and list-buckets succeeds (possibly with an empty bucket list).


Explicit deny example

A second user (lab-explicit-user) carries a customer-managed policy with both Allow and Deny on s3:ListAllMyBuckets. Switch to that user's profile before the commands below. The explicit Deny wins even though an Allow exists for the same action.

List the attached policy:

bash
aws iam list-attached-user-policies --user-name lab-explicit-user
output
{
    "AttachedPolicies": [
        {
            "PolicyName": "lab-explicit-deny-policy",
            "PolicyArn": "arn:aws:iam::123456789012:policy/lab-explicit-deny-policy"
        }
    ]
}

The policy JSON contains overlapping Allow and Deny statements:

json
{
  "Sid": "AllowListBuckets",
  "Effect": "Allow",
  "Action": "s3:ListAllMyBuckets",
  "Resource": "*"
},
{
  "Sid": "DenyListBuckets",
  "Effect": "Deny",
  "Action": "s3:ListAllMyBuckets",
  "Resource": "*"
}

Call list-buckets as the explicit-deny user:

bash
aws s3api list-buckets
output
aws: [ERROR]: An error occurred (AccessDenied) when calling the ListBuckets operation: User: arn:aws:iam::123456789012:user/lab-explicit-user is not authorized to perform: s3:ListAllMyBuckets with an explicit deny in an identity-based policy: arn:aws:iam::123456789012:policy/lab-explicit-deny-policy

The error text tells you:

  • Deny type — explicit deny
  • Policy layer — identity-based policy
  • Policy ARN — included here; open that policy JSON and find the Deny statement (not another broad Allow when the ARN is present)

Simulation confirms explicitDeny and names the denying statement inside MatchedStatements:

bash
aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::123456789012:user/lab-explicit-user \
  --action-names s3:ListAllMyBuckets \
  --resource-arns "*"
output
{
  "EvalDecision": "explicitDeny",
  "MatchedStatements": [
    {
      "SourcePolicyId": "lab-explicit-deny-policy",
      "SourcePolicyType": "user-managed"
    }
  ]
}

Fix explicit deny

When an explicit Deny matched:

  • Deny is unintended — edit the customer-managed policy and remove the DenyListBuckets statement, or detach the denying policy; after propagation, simulation should return allowed and list-buckets should succeed
  • Deny is intentional — correct the request context so the Deny condition no longer matches (wrong Region, missing session tag, unexpected network path, MFA requirement, and similar) instead of removing the guardrail

Why explicit deny wins

AWS policy logic treats Deny as final. When both Allow and Deny match the same request, Deny determines the outcome.

Situation EvalDecision Typical error clue
No applicable Allow implicitDeny because no identity-based policy allows
Allow matches, no Deny allowed API call succeeds
Deny matches (with or without Allow) explicitDeny with an explicit deny in plus policy type (ARN when provided)

Adding another Allow does not override an applicable explicit Deny:

  • Unintended deny — remove or narrow the Deny statement
  • Intentional guardrail — fix request context so the Deny condition no longer matches

Policy types that can deny

Identity-based policies are the simplest place to learn explicit versus implicit deny. Other AWS policy layers can also contribute a Deny or fail to provide a required Allow, but their evaluation rules differ. The AccessDenied message can help identify which layer to investigate.

Policy type Implicit deny wording (examples) Explicit deny wording (examples)
Identity-based no identity-based policy allows explicit deny in an identity-based policy
Permissions boundary no permissions boundary allows explicit deny in a permissions boundary
Organization SCP no service control policy allows explicit deny in a service control policy
Session policy (implicit when session lacks Allow) explicit deny in a session policy
Resource-based varies by service explicit deny in a resource-based policy
Resource control policy (RCP) depends on evaluation context explicit deny in a resource control policy
VPC endpoint policy no VPC endpoint policy allows explicit deny in a VPC endpoint policy

sts:AssumeRole failures can also report no role trust policy allows or explicit deny in the role trust policy when the role trust policy blocks the caller.

When AdministratorAccess is attached but the call still fails with explicit deny from a boundary or SCP, see AccessDenied despite AdministratorAccess for the layer-by-layer walkthrough.


Read AWS AccessDenied messages

Enhanced AccessDenied context comes from the AWS service response, not from the CLI classifying the failure:

  • Services may distinguish implicit deny from explicit deny and name the policy layer involved
  • The AWS CLI prints that service response text; it does not decide explicit versus implicit deny on its own
  • Not every service or request returns this enhanced format — a generic AccessDenied does not prove which case applied
Error fragment Meaning Next step
because no identity-based policy allows Implicit deny on identity policies Add or widen an Allow on the principal
because no permissions boundary allows Implicit deny inside the boundary cap Add Allow to the boundary or adjust design
because no service control policy allows SCP allow-list gap Update SCP at organization level
with an explicit deny in Explicit Deny statement matched Check the policy type shown in the error; if AWS includes a policy ARN, inspect that policy first
Generic AccessDenied only Context missing Use simulator or Access Troubleshooter

Some errors include an EncodedAuthorizationFailureMessage blob. A principal with sts:DecodeAuthorizationMessage can decode it when the service returns that field.


Use IAM Policy Simulator and Access Troubleshooter

aws iam simulate-principal-policy lets you test how the selected IAM principal's policies evaluate an action and resource without making the real API request. Its result can be allowed, implicitDeny, or explicitDeny:

  • allowed — an applicable Allow matched and no explicit Deny won
  • implicitDeny — the simulated permissions did not produce the required Allow
  • explicitDeny — an applicable Deny statement matched

Treat simulation as a diagnostic tool, not proof of the final live authorization result. Documented gaps include:

  • Resource control policies (RCPs)
  • Some VPC endpoint policy cases
  • Role chaining, resource policies, and other advanced request context

For the two lab users on s3:ListAllMyBuckets, simulation returned:

  • lab-implicit-user — implicitDeny with empty MatchedStatements
  • lab-explicit-user — explicitDeny with the DenyListBuckets sid
  • Both users — allowed after each respective fix

In the AWS Management Console

Open IAM → Policy simulator, select one principal such as lab-explicit-user, add s3:ListAllMyBuckets, and read the decision for that action. The panel below matches the explicit-deny outcome from the lab (styled from live simulator output, not a multi-principal composite):

IAM Policy simulator showing explicitDeny for lab-explicit-user on s3:ListAllMyBuckets

IAM Access Troubleshooter (public preview) can show evaluation for a failed request when AWS returns an authorization ID. Limitations to expect:

  • Feature is in public preview with gradual rollout
  • Authorization IDs are not returned for every service, API, or denied request
  • Use the same Region as the failed API call when the feature is available

Troubleshooting

Symptom What it means What to check
no identity-based policy allows Implicit deny User and group policies; add missing Allow
with an explicit deny in an identity-based policy Deny on identity Policy JSON for Effect: Deny on that action
explicit deny in a permissions boundary Boundary Deny Boundary JSON; permissions boundary row in IAM console
explicit deny in a service control policy Organization SCP SCP on account or parent OU
Simulator shows allowed, API still fails Layers or context the simulator omits Resource policy, endpoint policy, or caller profile
Allow added but still denied Explicit Deny elsewhere Search all applicable policies for Deny
Explicit deny but guardrail is intentional Request matched a Deny condition Region, tags, network path, MFA, or other request context

Summary

AWS IAM denies by default. An implicit deny occurs when there is no applicable explicit Deny, but the authorization evaluation still does not have the required Allow. In the identity-policy example in this article, that happens because no identity-based policy allows s3:ListAllMyBuckets. Service errors may state because no identity-based policy allows the action, and simulate-principal-policy returns implicitDeny with empty MatchedStatements.

Explicit deny means a Deny statement matched. It overrides any conflicting Allow, may appear in the error as with an explicit deny in plus policy type (and sometimes a policy ARN), and returns explicitDeny in simulation with the denying policy named in MatchedStatements.

The lab walked through both cases on s3:ListAllMyBuckets: attach an Allow to clear implicit deny, and remove or narrow a Deny statement — or fix request context when the deny is intentional. For denials from boundaries, SCPs, or resource policies, use the error policy type to pick the right layer rather than attaching another blanket administrator policy.


References


Frequently Asked Questions

Can Allow override explicit Deny?

No. When a Deny statement matches the request, AWS returns explicit deny even if one or more Allow statements also match. Options depend on intent:

  • Remove or narrow the Deny when the block is unintended
  • Correct request context when the Deny guardrail is intentional
  • Detach or replace the denying policy when it should not apply to the principal

What is default deny in AWS IAM?

Default deny means AWS rejects a request unless an applicable policy explicitly grants Allow and no applicable policy explicitly denies it. If no Allow matches, the outcome is implicit deny.

Why does AWS say no policy allows the action?

That phrase indicates implicit deny. IAM evaluated the relevant identity-based policies (on the user and its groups) and did not find an Allow for the action and resource. Attach or update a policy to grant the action, or confirm the call uses the intended principal.

Finished reading?Beta Get the key takeaways in seconds, then ask follow-up questions
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with 15+ years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)