Skip to main content
cd ../config-traps
risk/register/notaction-plus-allow-iams-silent-escalation-path.html
AWS IAM Policy Designcritical severityAWS IAM

NotAction Plus Allow: IAM's Silent Escalation Path

Severity
critical
Reviewed
12 Jul 2026
Remediation
~20 minutes
Overview

An IAM policy pairing Effect: Allow with NotAction grants every action AWS has not explicitly listed, not just the excluded services. The bound role can call sts:AssumeRole, lambda:UpdateFunctionCode, and ec2:RunInstances to escalate privileges, and the exposed surface silently grows as AWS ships new API actions each quarter.

Operational summary

At a glance

Symptom
Role assumes broad allow permissions covering every current and future AWS action not named in the exclusion list
Likely cause
IAM policy statement using Effect: Allow combined with NotAction instead of an explicit Action list
Impact
Account-wide privilege escalation via AssumeRole, PassRole, and compute pivots, worsening automatically as AWS adds new API actions
Verification signal
Re-run the detection test and a controlled negative-path test.
Safe correction
Restrict NotAction to Effect: Deny only; replace Allow statements with explicit Action lists generated from Access Analyzer policy generation
Rollback or recovery
Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

The Trap

Writing an IAM permission statement with "Effect": "Allow" and NotAction instead of a curated Action list. The pattern usually appears when someone tries to write a “grant everything except administration” policy for a contractor, CI runner, or third-party integration role.

The Default State

A typical offender looks like this: {"Effect": "Allow", "NotAction": ["iam:*", "organizations:*"], "Resource": "*"}. The author reads this as “allow everything except IAM and Organizations actions.” That reading is wrong. NotAction paired with Allow actually means “allow every action that AWS has not named in this list,” including every action that exists today under s3, ec2, lambda, sts, kms, and every action AWS ships tomorrow under services that don’t yet exist. Terraform modules copied from internal wikis and AWS console policy templates propagate this shape because it looks compact and self-documenting.

The Blast Radius

The role granted this policy can call sts:AssumeRole to pivot into other roles in the account, lambda:UpdateFunctionCode to inject payloads into privileged functions, and ec2:RunInstances with an attached instance profile carrying broader permissions than the original role itself. None of this requires a policy change on the attacker’s part — it is already permitted. Worse, AWS adds dozens of new API actions per quarter. A NotAction/Allow policy that passed a security review six months ago now covers a materially larger action surface without anyone touching the policy document. An access review signed off in Q1 is silently wrong by Q3, and nothing in CloudTrail or IAM’s policy JSON flags the drift.

The Lead Mechanic Fix

Never combine NotAction with Effect: Allow. If an exclusion pattern is genuinely required, use NotAction only under Effect: Deny, layered as a permissions boundary or Service Control Policy, never as the primary grant. Replace the allow-list with an explicit Action array generated from real usage: run aws accessanalyzer start-policy-generation against 90 days of CloudTrail data for the role, then attach the resulting least-privilege policy. Enforce this account-wide by requiring every role creation to set iam:PermissionsBoundary to a boundary policy that itself uses Effect: Deny with NotAction covering the approved service set, so any Allow statement attached later is capped regardless of how it is written.

03

Apply the safer control

Before you change production

Confirm the affected scope, export the current configuration, and test the replacement control in a non-production environment first.

Fix commands and configuration

NotAction
Effect: Allow
Effect: Deny
04

Verify, roll back or escalate

Verify

Re-run the detection test and a controlled negative-path test. Confirm the unsafe behaviour is blocked while approved traffic still succeeds.

Rollback

Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

Escalate

Escalate when the blast radius is uncertain, the control cannot be tested safely, or remediation requires an outage or security exception.

After remediation

Further reading stays below the corrective workflow and is selected by platform, category and shared technical keywords.

Discover more

Connected KBY resources