skip to content

In AWS IAM, what is the difference between an implicit deny and an explicit Deny, and what does each mean for how you write and troubleshoot policies?

level: juniorimportance: must knowfreq 72%

answer

  1. default is no, not yes
  2. one is absence, one is a statement
  3. additive versus final
  4. nothing outvotes Effect Deny
  5. the error message tells you which

basics

~20 s

Every AWS request starts denied. An implicit deny is simply the absence of any matching Allow, and adding an Allow fixes it. An explicit Deny is a statement with Effect Deny, and no Allow anywhere can override it.

solid answer

~40 s

IAM is default-deny: if nothing in any applicable policy allows the action, the request fails with an **implicit deny**. That is the state you are in before you attach anything, and the cure is to add a matching `Allow` in an identity-based or resource-based policy. An **explicit Deny** is a statement with `"Effect": "Deny"`, and it is absolute — once any applicable policy denies the action, the request fails no matter how many Allows exist elsewhere, including `AdministratorAccess`. Practically this means Allows are additive and negotiable while Denies are final, so explicit Deny is the tool for non-negotiable rules (block a region, require MFA, protect a set of resources) and you should never reach for it to "undo" a broad Allow you could simply have scoped down instead.

code

json · 17 lines
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowAllS3",
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "*"
    },
    {
      "Sid": "NeverDeleteBuckets",
      "Effect": "Deny",
      "Action": "s3:DeleteBucket",
      "Resource": "*"
    }
  ]
}

go deeper

for a junior

Be ready to say that AWS denies by default, that adding an Allow fixes an implicit deny, and that a statement with Effect Deny wins over every Allow. Knowing those three sentences cleanly is what is being tested.

for a middle

Explain why the asymmetry exists and where Denies can come from besides the principal's own policies, and read an AccessDenied message well enough to say whether more permissions or fewer denies is the fix.

for a senior

Show judgment about when a Deny is appropriate. Talk about the blast radius of a mis-conditioned Deny, the difficulty of diagnosing one written in another account, and your preference for narrow Allows over Allow-plus-Deny patching.

for a principal

Own the policy about policy: which invariants deserve a non-overridable Deny, who may author one, how those Denies are reviewed and tested before rollout, and how teams break glass when a central Deny turns out to be wrong.

## The starting point: nothing is permitted AWS authorization begins from a closed default. When a request arrives — `s3:GetObject`, `ec2:TerminateInstances`, anything — the evaluator assumes the answer is no and then looks for a reason to say yes. A brand-new IAM user with no policies attached can call nothing at all, not even read its own name. This is called the **default deny** or **implicit deny**. ## Implicit deny: the absence of an Allow An implicit deny is not something you write. It is the result of the search for a matching `Allow` coming up empty. Any of these produce it: - no policy is attached to the principal at all; - a policy is attached but its `Action` does not cover the call (an `s3:GetObject` allow does not cover `s3:ListBucket`, which is a separate action); - the `Resource` does not match the ARN in the request (`arn:aws:s3:::my-bucket` matches the bucket but not the objects inside it, which are `arn:aws:s3:::my-bucket/*`); - a `Condition` on the Allow does not hold at request time, so the statement does not match. The defining property is that an implicit deny is **overridable**: attach or widen a policy that allows the action, and the request now succeeds. Nothing has to be removed first. ## Explicit Deny: a statement that ends the argument An explicit Deny is a statement you author with `"Effect": "Deny"`. If any policy that applies to the request contains a matching Deny — an identity-based policy, a resource-based policy such as an S3 bucket policy, a permissions boundary, a session policy, or a service control policy in AWS Organizations — the final decision is deny. There is no Allow strong enough to beat it, and there is no ordering trick that helps: policies are not evaluated top to bottom like a firewall rule list, so a Deny later in the same document, or in a completely different document, still wins. ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:*", "Resource": "*" }, { "Effect": "Deny", "Action": "s3:DeleteBucket", "Resource": "*" } ] } ``` This principal can do everything in S3 except delete a bucket, and attaching `AdministratorAccess` on top changes nothing. ## Why the asymmetry exists The rule "Allows are additive, Deny is final" is what makes delegated administration safe. If Denies could be outvoted, then anyone able to attach one more policy could unwind a security control. Because they cannot, a central team can write a rule once — deny anything outside `eu-central-1`, deny disabling CloudTrail, deny access to the audit bucket — and know that no account admin, no future policy edit, and no automation can quietly re-enable it. The cost of that power is that Denies are blunt. A Deny with a `Condition` you got slightly wrong takes down callers that were never the target, and because it wins everywhere, it is the hardest kind of breakage to diagnose from inside the affected account. ## Troubleshooting: which one are you looking at? When you get `AccessDenied`, the first useful question is which of the two you hit, because the remedies are opposite. Modern AWS error messages usually tell you: a message ending in *"because no identity-based policy allows the ... action"* is an implicit deny — go add or widen a policy. A message naming *"an explicit deny in a service control policy"*, or in an identity-based or resource-based policy, means adding permissions is wasted effort; you must find and change the denying statement, which often lives in another account or another team's repository. ## Writing guidance Prefer scoping the Allow over patching it with a Deny. `Allow s3:GetObject on arn:aws:s3:::reports/*` is easier to read and reason about than `Allow s3:*` plus three Deny statements. Reserve explicit Deny for invariants that must survive every future edit: guardrails on regions and root-like actions, protection of security-relevant resources, and conditions such as requiring MFA or a specific VPC endpoint. And remember that a Deny in a resource-based policy protects the resource against principals in other accounts too — it is not just an identity-side tool.

  • If Allows are additive, does the order of statements inside a policy document matter?
    No. IAM does not evaluate statements top to bottom like a firewall ruleset. Every applicable statement in every applicable policy is considered, then the decision is computed: deny if any Deny matched, otherwise allow if any Allow matched, otherwise implicit deny. Reordering a document changes nothing, which is why a Deny placed first and a Deny placed last behave identically.
  • When is an explicit Deny the wrong tool?
    When you could simply write a narrower Allow. Broad-Allow-plus-Deny policies are hard to read, and each Deny is a landmine for future callers because it cannot be overridden locally. Denies belong to invariants you want enforced against everyone forever — region restrictions, protecting audit resources, requiring MFA — not to trimming a permission set you control.
  • Can a resource-based policy's explicit Deny block an account's own administrator?
    Yes. A bucket policy that denies a principal is evaluated for every request to that bucket, including from principals in the owning account, so an administrator hits the same wall. The recovery path is to edit the resource policy itself with a principal the policy does not deny — which is why locking yourself out with an over-broad Deny in a bucket or KMS key policy is a real operational risk.

saying these in an interview costs you the question

  • Thinks an admin policy can override an explicit Deny
  • Believes IAM evaluates statements in document order
  • Calls the default state 'allow until denied'
  • Assumes only identity policies can contain a Deny
  • Uses broad Allow plus Deny where a narrow Allow would do

context