The Duplicitous Nature of AWS Identity and Access Management (IAM)
Jason Kao (Founder · Fog Security)
fwd:cloudsec North America 2025 · Day 2 · Track 2 - Crestone
Overview
Jason Kao, founder of Fog Security, delivered a methodical examination of duplicate IAM permissions in AWS -- cases where two or more distinct IAM permissions produce the same outcome or effect, but managing or denying one does not necessarily affect the other. This is not about redundant policy statements granting the same permission twice; it is about architecturally different IAM actions that accomplish identical results through separate API paths. The talk covers concrete examples across SQS, SES, KMS, Identity Center (formerly SSO), and AWS Accounts, then explores why these duplicates exist, how AWS has attempted to address them, and why they create serious complexity for prevention, detection, and governance strategies.

Key moments
- 2:00 18,724 IAM permissions across 444 service prefixes as of today
- 6:00 SES V1 and V2 duplicate permissions: same prefix, different API versions
- 8:00 SES account management and identity policy duplicates across API versions
- 10:00 SQS: AddPermission vs SetQueueAttributes both modify resource-based policies
- 12:00 Side-by-side comparison of duplicate API request formats
- 14:00 AWS resolutions: permission retirement, condition keys, and documentation
- 18:00 New service reference JSON reveals multi-category permission classifications
- 20:00 Detection and prevention strategy challenges for duplicate permissions
The Duplicitous Nature of AWS Identity and Access Management (IAM)
Speakers: Jason Kao
Conference: fwd:cloudsec North America 2025
YouTube: https://www.youtube.com/watch?v=gQw586n5W9s
Overview
Jason Kao, founder of Fog Security, delivered a methodical examination of duplicate IAM permissions in AWS -- cases where two or more distinct IAM permissions produce the same outcome or effect, but managing or denying one does not necessarily affect the other. This is not about redundant policy statements granting the same permission twice; it is about architecturally different IAM actions that accomplish identical results through separate API paths. The talk covers concrete examples across SQS, SES, KMS, Identity Center (formerly SSO), and AWS Accounts, then explores why these duplicates exist, how AWS has attempted to address them, and why they create serious complexity for prevention, detection, and governance strategies.
Background
▶ Watch: 18,724 IAM permissions across 444 service prefixes as of today (2:00)
AWS IAM has grown from approximately 7,000 permissions in 2020 to 18,724 permissions across 444 service prefixes as of the morning of the talk. With over 200 services, some having multiple service prefixes, the combinatorial complexity of IAM policy management is staggering. Kao brings direct experience from building cloud security at Fidelity Investments, offensive cloud security consulting at Praetorian, and security research at CloudQuery before founding Fog Security.
The shared responsibility model frames the problem: AWS provides tools like IAM and documentation for customers to secure their environments, but the inherent complexity and inconsistency in how those tools work creates significant risk. Kao draws an IKEA analogy -- some AWS services come with clear assembly instructions, while others leave customers guessing at how the pieces fit together.
Existing AI assistants like Perplexity and ChatGPT, when asked about "duplicate IAM permissions," describe redundant or overlapping permissions granted to a user or role. That is not what this talk addresses. Kao's definition is precise: two or more AWS IAM permissions that correspond to the same outcome or effect, where managing one permission does not necessarily affect the other.
Key Findings
▶ Watch: SES account management and identity policy duplicates across API versions (8:00)
Kao documented duplicate permissions across multiple AWS services, each following the same pattern: multiple API actions achieve the same result, but they are classified differently, logged differently in CloudTrail, and governed by different policy mechanisms.
SQS (Simple Queue Service): sqs:AddPermission and sqs:SetQueueAttributes can both modify a queue's resource-based policy. Critically, sqs:AddPermission is classified as permissions management while sqs:SetQueueAttributes is classified as write -- meaning tools and policies categorizing by access level will treat them differently. AWS documentation acknowledges this and recommends denying both actions, but sqs:SetQueueAttributes cannot be blocked entirely because it controls other queue properties beyond just policies.
SES (Simple Email Service): SES V1 (2011) and SES V2 (2020) APIs create parallel permissions under the same ses: service prefix. Sending raw email, sending templated email, managing account settings, managing identity policies, and deleting identity policies all have V1 and V2 variants that produce the same outcomes.
KMS (Key Management Service): kms:RetireGrant and kms:RevokeGrant both remove access to a KMS key by deleting a key grant, but they are governed by different mechanisms. RetireGrant is authorized primarily through the grant itself (via the retiring principal), while RevokeGrant is authorized through the key policy. Permissions to retire a grant cannot be granted through an IAM policy, only through the grant's retiring principal field.
Identity Center (formerly SSO): Adding permissions to a permission set can be done via sso:PutPermissionsPolicy or sso:PutInlinePolicyToPermissionSet. Managing group membership can be done via identitystore:CreateGroupMembership or sso-directory:AddMemberToGroup. These pairs reflect the SSO-to-Identity Center rebrand, with legacy and modern API paths coexisting.
AWS Accounts: Modifying contact information can be done via aws-portal:ModifyAccount (console only) or account:PutContactInformation (API only), depending on when the account or organization was created.
A major finding emerged the day before the talk: AWS released new service authorization reference JSON files with annotations showing that some permissions can be classified in multiple categories simultaneously. sqs:SetQueueAttributes appeared as both "write" and "permissions management" in the new annotations, breaking the assumption of a single-category classification model that existing security tools rely on.
Technical Deep Dive
▶ Watch: Side-by-side comparison of duplicate API request formats (12:00)
The technical complexity manifests in several dimensions. First, the classification taxonomy is inconsistent. AWS categorizes permissions into buckets: list, read, write, tagging, and permissions management. Duplicate permissions that achieve the same outcome are often placed in different categories, meaning security tools that filter by access level (e.g., "show me all permissions management actions") will miss one of the pair.
Second, CloudTrail logging uses different event names for each API action. If a security team monitors for SQS policy changes by looking for AddPermission events, they will miss policy changes made via SetQueueAttributes. The event names are different, the request structures are different, and the metadata is different.
Third, the console vs. API split means some permissions only apply in the web console while others only apply via API calls. For AWS Account contact information, the applicable permission depends on when the account was created, adding a temporal dimension to the complexity.
Fourth, denial strategies are complicated by scope differences. Denying sqs:AddPermission cleanly blocks one path to modify queue policies. Denying sqs:SetQueueAttributes blocks the other path but also blocks legitimate queue configuration changes, because the action controls more than just policies.
AWS has addressed some duplicates through permission retirement (e.g., aws-portal: prefix permissions retired in July 2023 with bulk policy migrator scripts), IAM condition keys (e.g., ses:ApiVersion to filter by SES API version), and documentation noting the need to deny multiple actions. However, these solutions are inconsistent in approach and coverage.
Demo / Proof of Concept
▶ Watch: AWS resolutions: permission retirement, condition keys, and documentation (14:00)
No live demo was performed. The talk was structured around detailed slides showing API request formats, console screenshots, and documentation excerpts for each duplicate permission pair, with side-by-side comparisons of how the same outcome is achieved through different API paths.
Defensive Implications
▶ Watch: Detection and prevention strategy challenges for duplicate permissions (20:00)
Security teams need to audit their IAM deny policies and SCPs to ensure they cover all API paths that achieve a given outcome, not just the most obvious one. For SQS specifically, blocking resource-based policy modifications requires denying both sqs:AddPermission and sqs:SetQueueAttributes, though the latter has collateral impact on legitimate operations.
CloudTrail monitoring and detection rules must account for all duplicate API actions. A detection rule for SQS policy changes that only watches for AddPermission events is incomplete. Security teams should review AWS's newly released service authorization reference JSON files, which now include multi-category annotations.
Organizations should implement Resource Control Policies (RCPs) and Service Control Policies (SCPs) that account for duplicate permissions when establishing data perimeters. When evaluating security tooling, teams should verify that the tools handle permission classification overrides and are aware of the multi-category annotations now available in the service reference.
The broader lesson is that purpose-driven IAM configuration requires deep understanding of API-level nuance, and security teams cannot rely on permission names or single-category classifications to build complete policies.
Key Takeaways
- AWS contains duplicate IAM permissions where different API actions achieve the same outcome but are governed, classified, and logged independently
- As of the talk, AWS had 18,724 permissions across 444 service prefixes, with documented duplicates in SQS, SES, KMS, Identity Center, and AWS Accounts
- Permission classification (write vs. permissions management) is inconsistent across duplicates, and AWS now supports multi-category classification in service reference JSON files
- CloudTrail event names differ for duplicate actions, meaning detection rules must cover all paths to be effective
- Deny strategies are complicated because blocking one duplicate action may have broader collateral effects on legitimate operations
- AWS has addressed some duplicates through permission retirement, condition keys, and documentation, but the approaches are inconsistent across services
About the Speaker(s)
Jason Kao is the founder of Fog Security, where he focuses on data perimeters and cloud ransomware prevention. Previously, he built out cloud security at Fidelity Investments, performed offensive cloud security consulting at Praetorian, and conducted security research and solutions engineering at CloudQuery. He plans to expand his duplicate permissions research across additional AWS services and release associated tooling.
Reviews
Dr. Zero (Offensive Security Researcher) — SOLID
A thorough cataloguing of duplicate IAM permissions that create real blind spots in AWS security policies and detection rules. Not flashy, no exploits dropped, but this is the kind of deep platform knowledge that actually matters when you're trying to build or break through IAM guardrails. The SQS AddPermission vs SetQueueAttributes split is a legitimate detection gap that's probably being missed in production right now.
Heather Calloway (CISO) — STRONG ACCEPT
A methodical and deeply relevant examination of architectural inconsistencies in AWS IAM that directly undermine the effectiveness of preventive and detective controls. Any organization relying on SCPs, IAM deny policies, or CloudTrail-based detection without accounting for duplicate permissions has blind spots in their security posture that this research exposes.