Instantly understand and fix AWS AccessDenied errors.
AWS IAM debugging costs teams hours per incident. awsdeny converts cryptic AccessDenied errors into clear, actionable explanations — telling you exactly what blocked the request, why, and how to fix it.
Every AWS developer has seen this:
User: arn:aws:iam::123456789012:role/MyRole is not authorized to perform: s3:GetObject
on resource: arn:aws:s3:::my-bucket/data.csv
This error doesn't tell you:
- Which policy blocked it (SCP? Permission boundary? Bucket policy? Missing identity policy?)
- Why it was denied (a condition failed? wrong region? cross-account trust?)
- How to fix it (what exact policy change is needed?)
awsdeny answers all three in seconds.
$ awsdeny explain --error "User: arn:aws:iam::123456789012:role/MyRole is not authorized
to perform: s3:GetObject on resource: arn:aws:s3:::my-bucket/data.csv because no
identity-based policy allows the s3:GetObject action"
Access Denied
Action: s3:GetObject
Resource: arn:aws:s3:::my-bucket/data.csv
Principal: arn:aws:iam::123456789012:role/MyRole
Analysis:
Type: Implicit deny
Source: Identity-based policy
Reason: No identity-based policy (attached to your role/user/group) grants the
required permission. This is an implicit deny — there's no explicit
Deny statement, but there's also no Allow.
Suggested fixes:
1. Add to your policy: {"Effect": "Allow", "Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/data.csv"}
2. Attach an AWS managed policy that includes this permission
3. Use a different role/user that already has this permission
Confidence: very-high (heuristic match)
CloudWatch Insights query to find similar events:
fields @timestamp, errorCode, errorMessage, eventName,
userIdentity.arn | filter errorCode = 'AccessDenied' and eventName =
'GetObject' and userIdentity.arn = 'arn:aws:iam::123456789012:role/MyRole'
| sort @timestamp desc | limit 20
- 23 built-in heuristic patterns covering SCPs, permission boundaries, resource policies, cross-account access, conditions (VPC endpoint, IP, MFA, encryption, ABAC), and common misconfigurations
- Ready-to-paste policy fix snippets for identity policies, trust policies, KMS key policies, permission boundaries, and session policies
- Action typo detection — catches mistakes like
s3:GetObjectsinstead ofs3:GetObject - CloudWatch Insights queries — auto-generates the query to find similar events in your logs
- Offline policy analysis — analyze local policy files without AWS credentials (
--policy-file) - AWS enrichment (Pro) — fetches the actual policy, lists attached policies, ranks which one to edit, and simulates the call to verify
- CloudTrail analysis (Pro) — parse CloudTrail events with full context (source IP, VPC endpoint, MFA status)
- CI/CD native — GitHub Action with PR comments, job summary, SARIF output, and structured outputs
- Works everywhere — single binary for Linux, macOS, and Windows; supports AWS, GovCloud, and China partitions
Download from GitHub Releases:
# macOS (Apple Silicon)
curl -Lo awsdeny.tar.gz https://github.com/leredteam/awsdeny/releases/latest/download/awsdeny_darwin_arm64.tar.gz
tar xzf awsdeny.tar.gz && sudo mv awsdeny /usr/local/bin/
# Linux (amd64)
curl -Lo awsdeny.tar.gz https://github.com/leredteam/awsdeny/releases/latest/download/awsdeny_linux_amd64.tar.gz
tar xzf awsdeny.tar.gz && sudo mv awsdeny /usr/local/bin/go install github.com/leredteam/awsdeny@latest# Explain an error
awsdeny explain --error "User: arn:aws:iam::123:role/MyRole is not authorized to perform: s3:GetObject on resource: arn:aws:s3:::bucket/key"
# Pipe from your terminal
aws s3 cp s3://bucket/key . 2>&1 | awsdeny explain --stdin
# Analyze a local policy file (no AWS credentials needed)
awsdeny explain --error "<error>" --policy-file my-policy.json
# JSON output for automation
awsdeny explain --error "<error>" --format json
# Deep analysis with AWS credentials (Pro)
awsdeny explain --error "<error>" --enrich --profile my-profileawsdeny uses a pragmatic, layered approach — starting with offline heuristics and going deeper with AWS API calls when requested:
| Level | What it does | Requires |
|---|---|---|
| 1 | Parse error + match against 23 heuristic patterns | Nothing (offline) |
| 2 | Fetch and analyze policy documents + rank attached policies | AWS credentials or --policy-file |
| 3 | Run iam:SimulatePrincipalPolicy with context to verify |
AWS credentials |
| 4 | Parse CloudTrail events for full context (IP, VPC, MFA) | CloudTrail JSON |
Level 1 and --policy-file are free and work offline. Levels 2-4 with --enrich require a Pro license.
Policy types: SCP explicit/implicit deny, permission boundaries, identity policies, resource policies (S3, KMS), session policies, VPC endpoint policies
Conditions: VPC endpoint, IP/CIDR/network restrictions, MFA, encryption (SecureTransport, SSE), tag-based ABAC, time-based
Cross-account: AssumeRole trust policy issues, resource access, missing ExternalId
Common issues: S3 404-as-403, service-linked roles, root user restrictions, EC2 encoded errors, wildcard resource requirements, action typos
- name: Deploy
id: deploy
run: aws s3 cp ./dist s3://my-bucket/
continue-on-error: true
- uses: LeRedTeam/awsdeny@v0.1.0
if: failure()
with:
error: ${{ steps.deploy.outputs.stderr }}
enrich: true
comment-on-pr: true
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWSDENY_LICENSE_KEY: ${{ secrets.AWSDENY_LICENSE_KEY }}| Format | Flag | Use case |
|---|---|---|
| Human | --format human (default) |
Terminal debugging |
| JSON | --format json |
Automation and scripting |
| SARIF | --format sarif (Pro) |
GitHub Code Scanning, VS Code |
| GitHub | --format github (Pro) |
PR comments |
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"iam:GetPolicy",
"iam:GetPolicyVersion",
"iam:ListAttachedRolePolicies",
"iam:SimulatePrincipalPolicy"
],
"Resource": "*"
}]
}Optional: sts:DecodeAuthorizationMessage, organizations:DescribePolicy
If any API call fails, awsdeny gracefully falls back to offline analysis.
| Feature | Free | Pro |
|---|---|---|
| Error parsing + 23 heuristic patterns | Yes | Yes |
| Action typo detection | Yes | Yes |
| CloudWatch Insights query | Yes | Yes |
| Human + JSON output | Yes | Yes |
Offline policy analysis (--policy-file) |
Yes | Yes |
| Stdin piping | Yes | Yes |
| GitHub Action job summary | Yes | Yes |
--enrich (policy fetch + simulation) |
Yes | |
| Ranked policy suggestions | Yes | |
| Principal introspection | Yes | |
| CloudTrail analysis | Yes | |
| SARIF output | Yes | |
| GitHub Action PR comments | Yes |
- No credentials stored — uses the AWS default credential chain only
- No telemetry — zero phone-home, zero analytics, zero tracking
- No data transmitted — all analysis is local (AWS API calls only with
--enrich) - Credential sanitization — output is scanned for access keys, secret keys, session tokens, and known STS token patterns
- Offline license validation — cryptographic signature verification, no license server
- All AWS partitions — supports
aws,aws-us-gov, andaws-cn
Existing IAM tools generate policies, lint policies, or audit permissions. None of them explain why a specific API call failed or what to change to fix it. awsdeny fills that gap — it's a debugging tool, not a policy tool.
AGPL-3.0 (COPYING). Commercial licenses available for proprietary use.
The most valuable contributions are unmatched error patterns. Please file an issue with:
- The AccessDenied error message (anonymize account IDs if needed)
- What you expected awsdeny to explain
- What it actually output
- iampg — Generate least-privilege IAM policies from real AWS API calls