Back to Blog
June 18, 2026

AWS IAM NotAction vs Deny: The Misread Statement That Grants Everything

IAM policies have a handful of elements that look intuitive and behave in ways that surprise almost everyone. NotActionis the clearest example. Its name suggests denial — "not this action" — but it does not deny anything. When paired with "Effect": "Allow", it grants access to every action in all of AWS except the ones you listed. That is almost always the opposite of what was intended.

This article explains exactly what NotAction does, where the confusion originates, the one legitimate use case, and how to rewrite the dangerous pattern correctly.

What NotAction Actually Means

NotAction inverts the Action element. Instead of listing what a statement covers, you list what it excludes — and the statement covers everything else. The effect of the statement still comes from Effect: either Allow or Deny.

When you write "Effect": "Allow" with NotAction, you are allowing every action in the entire AWS service catalog except the ones in the list. Consider this policy:

{
  "Effect": "Allow",
  "NotAction": "s3:DeleteObject",
  "Resource": "*"
}

This statement does not prevent the principal from deleting S3 objects. It grants them permission to call every other action in AWS: iam:CreateUser, ec2:TerminateInstances, s3:GetObject on every bucket, kms:Decrypt, secretsmanager:GetSecretValue — everything. The single excluded action is the only thing they cannot do. This is functionally equivalent to granting AdministratorAccess minus one operation.

The missing s3:DeleteObject permission is a cosmetic gap, not a meaningful restriction. An attacker holding this policy can create new IAM users, attach policies, run EC2 instances, access secrets, and exfiltrate data freely.

Where the Confusion Comes From

The name NotActionis the source of the misread. In plain English, "not this action" sounds like a restriction. It feels like saying "do not allow this action" or "exclude this action from what is permitted."

But AWS IAM policy evaluation does not work that way. Allow statements are purely additive — they can only grant permissions, never remove them. There is no such thing as a partial grant with a carve-out. The only mechanism that restricts access in IAM is an explicit Deny. If you want to prevent a principal from doing something, you have two options: do not grant the permission in the first place, or add a separate statement with "Effect": "Deny".

NotAction does not add a third option. It only changes which actions an Allow or Deny statement covers. The additive-only nature of Allow is unchanged.

The Dangerous Pattern: Protect One Action While Granting Everything Else

The most common manifestation of this mistake starts with a reasonable goal. A developer wants to give a CI/CD role broad S3 access but prevent it from deleting the production bucket. They write:

{
  "Effect": "Allow",
  "NotAction": "s3:DeleteBucket",
  "Resource": "*"
}

The intent was to grant S3 access while blocking one dangerous operation. The actual result is a grant covering every action in AWS except bucket deletion. The CI/CD role can now create IAM users, modify security groups, access DynamoDB tables, read secrets from Parameter Store, and assume roles — none of which was intended.

The correct approach to this scenario has two parts. First, grant only the specific actions the CI/CD role actually needs. Second, if you want an explicit safety net against bucket deletion, add a separate Deny statement for that action. Explicit denies take precedence over allows in IAM evaluation, so a Deny on s3:DeleteBucket will hold even if another policy somewhere grants it.

When NotAction IS Actually Useful

There is one pattern where NotAction is the right tool: a Deny statement. When you write "Effect": "Deny" with NotAction, you are denying every action except the ones in the list — creating an effective allowlist of permitted operations. This is different from the dangerous Allow pattern because Deny overrides Allow across all policies.

The primary use case is AWS Organizations Service Control Policies (SCPs). An SCP with this pattern enforces an organization-wide service allowlist on an entire organizational unit. Every account in the OU is restricted to the listed actions, regardless of what their IAM policies grant:

{
  "Effect": "Deny",
  "NotAction": [
    "s3:GetObject",
    "s3:PutObject",
    "s3:DeleteObject",
    "sts:AssumeRole"
  ],
  "Resource": "*"
}

This SCP statement says: deny everything except these four actions. Any API call not in the list is blocked at the organization level, overriding any IAM policy in the affected accounts. This is a valid and intentional use of NotAction — the inversion is exactly what you want when building a service whitelist.

The key distinction is the effect. Deny + NotAction creates a service whitelist. Allow + NotAction creates an almost-unlimited grant with one cosmetic gap. Only the first of these is useful. The second is almost always a bug.

How to Fix the Allow + NotAction Trap

There are two correct approaches, depending on your intent.

Replace with an explicit allow list. List every action the principal actually needs. This is more work, but it is the correct security posture. Principle of least privilege requires enumerating what is allowed, not carving out exceptions from everything. If the list is long, scope it by service (e.g., s3:* on specific buckets) rather than reaching for NotAction.

Use a separate Deny for the blocked action. If you have a legitimate broad grant and want to add a specific restriction on top of it, add an explicit Deny statement. Here is the corrected version of the CI/CD scenario above:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowSpecificS3",
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"],
      "Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"]
    },
    {
      "Sid": "DenyDelete",
      "Effect": "Deny",
      "Action": "s3:DeleteObject",
      "Resource": "arn:aws:s3:::my-bucket/*"
    }
  ]
}

This policy grants exactly three S3 actions on one specific bucket and denies deletes explicitly. The scope is precise. There is no accidental grant of iam:CreateUser or anything else. The Deny on s3:DeleteObject is a belt-and-suspenders safety net, not a workaround.

Detecting NotAction Misuse in Your Policies

The pattern to flag is straightforward: any statement where Effect is Allow and NotAction is present. That combination is almost always a mistake. If Resource is also "*", the severity is critical — the principal effectively has administrator-level access minus one excluded action.

A few specific signals worth auditing:

  • Allow + NotAction + Resource "*". This is the highest-risk form. The excluded actions list is irrelevant in practice — the grant covers the entire AWS service catalog.
  • Allow + NotAction with a short exclusion list. A list of three or four excluded actions means the remaining surface area is enormous. Even a long exclusion list cannot close the gap effectively — there are thousands of AWS actions.
  • NotAction in customer-managed policies attached to roles. These are the policies most likely to be written by a developer who misread the semantics. AWS managed policies do not use Allow + NotAction.
  • NotAction in inline policies. Inline policies are harder to discover in bulk audits and are often written quickly. They are disproportionately likely to contain this mistake.

Policy documents need to be evaluated for effective permissions, not just scanned for known-bad strings. A rule that flags Allow + NotAction catches the pattern, but understanding the severity requires reasoning about what actions the exclusion list actually leaves uncovered — which varies by policy and by the other permissions attached to the principal.

Catch NotAction misuse before it ships

Paste an IAM policy and get AI-Powered analysis in seconds — free, no credit card.

Amazon Web Services (AWS) is a trademark of Amazon.com, Inc. Shieldly is not affiliated with, endorsed by, or sponsored by Amazon Web Services.