Introduction

S3 bucket policies control who can access bucket resources. When access is denied despite valid credentials, the bucket policy, IAM policy, ACLs, or public access settings are blocking the request. S3 evaluates all these together to determine access.

Symptoms

AWS CLI error:

```bash $ aws s3 cp file.txt s3://my-bucket/

upload failed: file.txt to s3://my-bucket/file.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied ```

Console error:

bash
Access Denied
You do not have permission to access this bucket.

Application error:

xml
<Error>
  <Code>AccessDenied</Code>
  <Message>Access Denied</Message>
  <RequestId>ABC123</RequestId>
</Error>

Common Causes

  1. 1.Bucket policy explicitly denies - Policy has Deny statement
  2. 2.Bucket policy doesn't allow principal - Principal not in Allow statement
  3. 3.IAM policy doesn't grant permission - User/role lacks S3 permissions
  4. 4.Public Access Block enabled - Blocks public bucket policies
  5. 5.ACL conflicts - Object or bucket ACL denies access
  6. 6.KMS encryption - KMS key policy doesn't allow access
  7. 7.VPC endpoint policy - Endpoint policy restricts access
  8. 8.Object ownership - Different AWS account owns object

Step-by-Step Fix

  1. 1.Check logs for specific error messages
  2. 2.Verify configuration settings
  3. 3.Test network connectivity
  4. 4.Review recent changes
  5. 5.Apply corrective action
  6. 6.Verify the fix

Step 1: Check Bucket Policy

```bash # Get bucket policy aws s3api get-bucket-policy --bucket my-bucket --output json

# If empty, no explicit policy exists (rely on IAM + ACLs) # If present, check for: # - Explicit Deny statements (these override Allow) # - Principal matching your user/role # - Action covering your operation (s3:GetObject, s3:PutObject, etc.) # - Resource matching the bucket and objects ```

Example bucket policy allowing specific user:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789:user/myuser"
      },
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ]
    }
  ]
}

Add missing principal:

bash
aws s3api put-bucket-policy --bucket my-bucket --policy '{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {"AWS": "arn:aws:iam::123456789:user/myuser"},
      "Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"],
      "Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"]
    }
  ]
}'

Step 2: Check IAM User/Role Permissions

```bash # Get your current identity aws sts get-caller-identity

# Check attached policies aws iam list-attached-user-policies --user-name myuser aws iam list-attached-role-policies --role-name myrole

# Verify permissions include needed S3 actions aws iam get-policy-version --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess --version-id v1

# For custom policies, check the policy document aws iam get-policy-version --policy-arn arn:aws:iam::123456789:policy/my-s3-policy --version-id v1 ```

Minimum IAM permissions for S3 access:

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

Step 3: Check Public Access Block Settings

```bash # Get public access block configuration aws s3api get-public-access-block --bucket my-bucket

# If enabled, it blocks: # - Public bucket policies # - Public ACLs # - Any public access to the bucket

# Remove public access block if public access is needed aws s3api delete-public-access-block --bucket my-bucket ```

Step 4: Check Bucket and Object ACLs

```bash # Get bucket ACL aws s3api get-bucket-acl --bucket my-bucket

# Get object ACL aws s3api get-object-acl --bucket my-bucket --key my-file.txt

# ACL grants can conflict with bucket policy # Check for explicit DENY or missing ALLOW for your canonical user ID ```

Set ACL for specific user:

```bash aws s3api put-bucket-acl --bucket my-bucket \ --grant-read 'id="CANONICAL_USER_ID"' \ --grant-write 'id="CANONICAL_USER_ID"'

# Get your canonical user ID aws s3api list-buckets --query Owner.ID ```

Step 5: Check KMS Encryption

```bash # Check bucket encryption aws s3api get-bucket-encryption --bucket my-bucket

# If using SSE-KMS, you need KMS permissions # Check KMS key policy aws kms get-key-policy --key-id KEY_ID --policy-name default ```

KMS key policy must allow your IAM principal:

json
{
  "Sid": "Allow S3 access",
  "Effect": "Allow",
  "Principal": {"AWS": "arn:aws:iam::123456789:user/myuser"},
  "Action": ["kms:Decrypt", "kms:GenerateDataKey"],
  "Resource": "*"
}

Step 6: Check VPC Endpoint Policy

```bash # If using VPC endpoint for S3 aws ec2 describe-vpc-endpoints \ --filters Name=service-name,Values=com.amazonaws.region.s3

# Check endpoint policy aws ec2 get-vpc-endpoint-policy-documents --vpc-endpoint-id vpce-12345

# Endpoint policy may restrict S3 access # Ensure policy allows your operations ```

Step 7: Use Policy Simulator

```bash # Test if IAM policy allows the action aws iam simulate-principal-policy \ --policy-source-arn arn:aws:iam::123456789:user/myuser \ --action-names s3:GetObject \ --resource-arns arn:aws:s3:::my-bucket/*

# Shows "allowed" or specific denial reason ```

Step 8: Check Object Ownership

```bash # For objects uploaded by other accounts aws s3api get-object-acl --bucket my-bucket --key uploaded-by-other.txt

# If object owner is different account, you need: # 1. Object ACL allowing your access # 2. Or bucket owner enforced setting

# Enable bucket owner enforced (recommended) aws s3api put-bucket-ownership-controls --bucket my-bucket \ --ownership-controls '{ "Rules": [{"ObjectOwnership": "BucketOwnerEnforced"}] }' ```

Step 9: Check for Explicit Deny

```bash # Explicit Deny always overrides Allow # Look for Deny statements in bucket policy aws s3api get-bucket-policy --bucket my-bucket \ --query 'Policy' --output text | jq '.Statement[] | select(.Effect=="Deny")'

# Common explicit denies: # - NotPrincipal (everyone except specified) # - Condition based restrictions # - IP address restrictions # - SSL/TLS requirements ```

Step 10: Test Access with Different Principal

```bash # Create test user or use different role aws sts assume-role --role-arn arn:aws:iam::123456789:role/test-role --role-session-name test

# Test with assumed role credentials aws s3 ls s3://my-bucket/

# If works, original principal is the issue # If fails, bucket configuration is the issue ```

S3 Access Evaluation Order

  1. 1.IAM user/role identity
  2. 2.VPC endpoint policy (if applicable)
  3. 3.Bucket policy (explicit Deny first)
  4. 4.Bucket ACL
  5. 5.Object ACL
  6. 6.KMS key policy (for encrypted objects)

Verification

```bash # Test access aws s3 ls s3://my-bucket/

# Upload test file echo "test" | aws s3 cp - s3://my-bucket/test.txt

# Download test file aws s3 cp s3://my-bucket/test.txt -

# Delete test file aws s3 rm s3://my-bucket/test.txt

# All should succeed without AccessDenied error ```

  • [Fix AWS S3 CORS Config Missing](/articles/fix-aws-s3-cors-config-missing)
  • [Fix AWS S3 Replication Not Working](/articles/fix-aws-s3-replication-not-working)
  • [Fix AWS S3 Lifecycle Rule Not Expiring](/articles/fix-aws-s3-lifecycle-rule-not-expiring)
  • [AWS troubleshooting: Fix IAM Permission Denied - Complete Tro](fix-iam-permission-denied)
  • [AWS cloud troubleshooting: AWS ACM Certificate Pending Validation Because the](aws-acm-certificate-pending-validation-wrong-route53-zone)
  • [AWS cloud troubleshooting: AWS ALB Returns 502 Because the Target Closed the ](aws-alb-502-target-closed-connection-keepalive-timeout-mismatch)
  • [AWS cloud troubleshooting: Fix AWS ALB CreateListener TargetGroupNotFound Err](aws-alb-createlistener-targetgroupnotfound)
  • [AWS cloud troubleshooting: Fix Aws Alb Lambda 502 Bad Gateway Issue in AWS](aws-alb-lambda-502-bad-gateway)

<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Fix AWS S3 Bucket Policy Access Denied", "description": "Troubleshoot S3 access denied errors. Fix bucket policies, IAM permissions, ACLs, and public access block settings.", "url": "https://www.fixwikihub.com/fix-aws-s3-bucket-policy-denied", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-04-02T00:09:44.402Z", "dateModified": "2026-04-02T00:09:44.402Z" } </script>