AWS S3 Bucket Misconfigurations: How Data Leaks Happen and How to Prevent Them

SCRs Team
March 16, 2026
14 min read
234 words
Share

S3 Misconfigurations: Still the #1 Cloud Security Risk

Despite years of warnings, S3 bucket misconfigurations caused over 80% of cloud data breaches in 2025 (Qualys Cloud Security Report). Billions of records — medical data, financial records, credentials — exposed because of simple configuration errors.

High-Profile S3 Breaches

CompanyRecords ExposedRoot Cause
Capital One106 millionSSRF + overpermissive IAM role
TwitchComplete source codeMisconfigured S3 access
Hobby Lobby138GB customer dataPublic bucket
Accenture40,000 passwordsFour public S3 buckets
U.S. Military1.8 billion social media postsUnsecured S3 bucket

Misconfiguration #1: Public Access via ACLs

# ❌ DANGEROUS: Making a bucket publicly readable
aws s3api put-bucket-acl --bucket my-data --acl public-read

# ❌ Even worse: Public write access
aws s3api put-bucket-acl --bucket my-data --acl public-read-write

Detection

# Check if any buckets have public ACLs
aws s3api get-bucket-acl --bucket BUCKET_NAME \
  | jq '.Grants[] | select(.Grantee.URI == "http://acs.amazonaws.com/groups/global/AllUsers")'
  
# List ALL public buckets in your account
for bucket in $(aws s3api list-buckets --query 'Buckets[].Name' --output text); do
  acl=$(aws s3api get-bucket-acl --bucket "$bucket" 2>/dev/null)
  if echo "$acl" | grep -q "AllUsers"; then
    echo "⚠️  PUBLIC: $bucket"
  fi
done

Fix: Block Public Access at Account Level

# ✅ Block ALL public access for the entire AWS account
aws s3control put-public-access-block \
  --account-id $(aws sts get-caller-identity --query Account --output text) \
  --public-access-block-configuration \
    BlockPublicAcls=true,\
    IgnorePublicAcls=true,\
    BlockPublicPolicy=true,\
    RestrictPublicBuckets=true

Misconfiguration #2: Overly Permissive Bucket Policies

// ❌ This policy allows ANYONE to read ALL objects
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": "*",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::my-bucket/*"
  }]
}
// ✅ Restrict to specific IAM role only
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::123456789012:role/AppServerRole"
    },
    "Action": ["s3:GetObject"],
    "Resource": "arn:aws:s3:::my-bucket/public/*"
  }, {
    "Effect": "Deny",
    "Principal": "*",
    "Action": "s3:*",
    "Resource": "arn:aws:s3:::my-bucket/*",
    "Condition": {
      "Bool": { "aws:SecureTransport": "false" }
    }
  }]
}

Misconfiguration #3: No Encryption

# ❌ No server-side encryption — data at rest is unencrypted
aws s3 cp secret.txt s3://my-bucket/

# ✅ Enable default encryption with AWS-managed keys
aws s3api put-bucket-encryption --bucket my-bucket \
  --server-side-encryption-configuration '{
    "Rules": [{
      "ApplyServerSideEncryptionByDefault": {
        "SSEAlgorithm": "aws:kms",
        "KMSMasterKeyID": "alias/my-s3-key"
      },
      "BucketKeyEnabled": true
    }]
  }'

Misconfiguration #4: No Versioning or Logging

Without versioning, a single delete command wipes data permanently. Without logging, you can't detect unauthorized access.

# ✅ Enable versioning
aws s3api put-bucket-versioning --bucket my-bucket \
  --versioning-configuration Status=Enabled

# ✅ Enable server access logging
aws s3api put-bucket-logging --bucket my-bucket \
  --bucket-logging-status '{
    "LoggingEnabled": {
      "TargetBucket": "my-access-logs-bucket",
      "TargetPrefix": "s3-logs/my-bucket/"
    }
  }'

# ✅ Enable CloudTrail data events for the bucket
aws cloudtrail put-event-selectors --trail-name my-trail \
  --event-selectors '[{
    "ReadWriteType": "All",
    "DataResources": [{
      "Type": "AWS::S3::Object",
      "Values": ["arn:aws:s3:::my-bucket/"]
    }]
  }]'

Misconfiguration #5: CORS Allowing All Origins

// ❌ Allows any website to read your S3 objects
{
  "CORSRules": [{
    "AllowedOrigins": ["*"],
    "AllowedMethods": ["GET", "PUT", "POST"],
    "AllowedHeaders": ["*"]
  }]
}

// ✅ Restrict to your domains only
{
  "CORSRules": [{
    "AllowedOrigins": ["https://myapp.com", "https://staging.myapp.com"],
    "AllowedMethods": ["GET"],
    "AllowedHeaders": ["Authorization"],
    "MaxAgeSeconds": 3600
  }]
}

Automated Detection with Terraform

# Secure S3 bucket module
resource "aws_s3_bucket" "secure" {
  bucket = "my-secure-bucket"
}

resource "aws_s3_bucket_public_access_block" "secure" {
  bucket = aws_s3_bucket.secure.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_s3_bucket_server_side_encryption_configuration" "secure" {
  bucket = aws_s3_bucket.secure.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "aws:kms"
      kms_master_key_id = aws_kms_key.s3.arn
    }
    bucket_key_enabled = true
  }
}

resource "aws_s3_bucket_versioning" "secure" {
  bucket = aws_s3_bucket.secure.id
  versioning_configuration { status = "Enabled" }
}

S3 Security Checklist

  • Account-level public access block enabled
  • No bucket ACLs granting public access
  • Bucket policies follow least privilege
  • Default encryption enabled (SSE-KMS preferred)
  • Versioning enabled on all data buckets
  • Server access logging or CloudTrail data events enabled
  • CORS restricted to specific origins
  • MFA Delete enabled for critical buckets
  • Lifecycle policies to expire/transition old objects
  • Regular audits with AWS Config rules or ScoutSuite
Editorial standards

Published by SecureCodeReviews

This article is part of our original AI security and cybersecurity content library. We show publish and update dates, keep company and policy pages public, and update important guidance when material changes affect readers.

Named author: SCRs Team
Published: Mar 16, 2026
Update status: current publication version

Questions or corrections?

Review our editorial standards, learn more about the company, or contact us if a page needs clarification.

Cloud Assessment

Need a cloud security review before rollout?

We review IAM, network exposure, storage security, deployment posture, and the misconfigurations that usually get missed in fast-moving teams.

AWS, Azure, and GCP posture reviews
IAM, storage, network, and encryption validation
Clear findings with prioritized fixes for engineering teams

Talk to SecureCodeReviews

Get a scoped review path fast

Manual review
Actionable fixes
Fast turnaround
Security-focused

Advertisement