AI & assistant-friendly summary

This section provides structured content for AI assistants and search engines. You can cite or summarize it when referencing this page.

Summary

A comprehensive guide to S3 security — bucket policies, encryption, access logging, Block Public Access, and the practices that prevent the data breaches that make headlines.

Key Facts

  • A comprehensive guide to S3 security — bucket policies, encryption, access logging, Block Public Access, and the practices that prevent the data breaches that make headlines
  • A comprehensive guide to S3 security — bucket policies, encryption, access logging, Block Public Access, and the practices that prevent the data breaches that make headlines

Entity Definitions

S3
S3 is an AWS service discussed in this article.

AWS S3 Security Best Practices: Preventing Data Exposure

Security & Compliance 9 min read

Quick summary: A comprehensive guide to S3 security — bucket policies, encryption, access logging, Block Public Access, and the practices that prevent the data breaches that make headlines.

Key Takeaways

  • A comprehensive guide to S3 security — bucket policies, encryption, access logging, Block Public Access, and the practices that prevent the data breaches that make headlines
  • A comprehensive guide to S3 security — bucket policies, encryption, access logging, Block Public Access, and the practices that prevent the data breaches that make headlines
AWS S3 Security Best Practices: Preventing Data Exposure
Table of Contents

S3 is the most widely used AWS service — and historically the most common source of cloud data breaches. Misconfigured S3 buckets have exposed customer records, credentials, backup databases, and sensitive business documents. Not because S3 is insecure, but because its flexibility makes misconfiguration easy.

AWS has significantly improved S3’s default security posture over the past few years. New buckets now block public access by default, object ownership is enforced, and ACLs are disabled. But legacy configurations, complex bucket policies, and cross-account access patterns still create risk. This guide covers the security practices that prevent S3 from becoming your organization’s next headline.

Block Public Access: The First Line of Defense

S3 Block Public Access (BPA) is the single most important S3 security control. It overrides any bucket policy or ACL that would make objects publicly accessible.

Four BPA settings:

SettingWhat It Blocks
BlockPublicAclsNew public ACLs from being applied
IgnorePublicAclsExisting public ACLs from granting access
BlockPublicPolicyNew public bucket policies from being applied
RestrictPublicBucketsPublic and cross-account access via public policies

Enable all four at the account level:

{
  "BlockPublicAcls": true,
  "IgnorePublicAcls": true,
  "BlockPublicPolicy": true,
  "RestrictPublicBuckets": true
}

When enabled at the account level, no bucket in that account can be made public — regardless of individual bucket settings. This is the default for new accounts, but older accounts may not have it enabled.

Exception handling: If you legitimately need a public bucket (static website hosting, public datasets), create it in a dedicated account with BPA disabled only for that specific bucket. Never disable account-level BPA in accounts that contain sensitive data.

Bucket Policies

Bucket policies are the primary access control mechanism for S3. They are powerful — and dangerous if written incorrectly.

Principle of Least Privilege

Every bucket policy should grant the minimum access required:

{
  "Effect": "Allow",
  "Principal": { "AWS": "arn:aws:iam::123456789012:role/DataProcessorRole" },
  "Action": ["s3:GetObject"],
  "Resource": "arn:aws:s3:::my-data-bucket/processed/*"
}

This policy grants read access to a specific IAM role, for a specific prefix only. Compare to the overly permissive alternative:

{
  "Effect": "Allow",
  "Principal": "*",
  "Action": "s3:*",
  "Resource": "arn:aws:s3:::my-data-bucket/*"
}

This grants full access to everyone on the internet. It appears in more bucket policies than you might expect.

Deny Policies

Explicit deny policies provide guardrails that cannot be overridden by other allow statements:

Deny unencrypted uploads:

{
  "Effect": "Deny",
  "Principal": "*",
  "Action": "s3:PutObject",
  "Resource": "arn:aws:s3:::my-bucket/*",
  "Condition": {
    "StringNotEquals": {
      "s3:x-amz-server-side-encryption": "aws:kms"
    }
  }
}

Deny access from outside your organization:

{
  "Effect": "Deny",
  "Principal": "*",
  "Action": "s3:*",
  "Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"],
  "Condition": {
    "StringNotEquals": {
      "aws:PrincipalOrgID": "o-your-org-id"
    }
  }
}

This aws:PrincipalOrgID condition restricts access to IAM principals within your AWS Organization — even if someone creates an IAM policy that references your bucket in another account outside your organization.

Deny non-TLS access:

{
  "Effect": "Deny",
  "Principal": "*",
  "Action": "s3:*",
  "Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"],
  "Condition": {
    "Bool": {
      "aws:SecureTransport": "false"
    }
  }
}

Encryption

Server-Side Encryption

S3 now encrypts all objects by default using SSE-S3 (AES-256). You do not need to configure anything for baseline encryption. However, for compliance and key management requirements, you have three options:

Encryption TypeKey ManagementCostUse Case
SSE-S3 (AES-256)AWS managed, automaticFreeDefault, general-purpose
SSE-KMSAWS KMS managed, per-key policiesKMS API costsCompliance, audit trail, key rotation
SSE-KMS with CMKCustomer-managed KMS keyKMS API costsMaximum control, cross-account key sharing

SSE-KMS advantages over SSE-S3:

  • CloudTrail logs every use of the KMS key (who accessed what, when)
  • Key policies provide an independent access control layer
  • Automatic key rotation (annual for AWS-managed keys, configurable for CMKs)
  • Key deletion scheduling with a waiting period (7-30 days) prevents accidental data loss

Recommendation: Use SSE-KMS with a customer-managed key for any bucket containing sensitive data (PII, financial data, healthcare records). The KMS API cost is minimal ($0.03 per 10,000 requests) and the audit trail is invaluable for compliance.

Client-Side Encryption

For data that must be encrypted before it leaves your application (zero-trust model), use the AWS Encryption SDK or S3 Encryption Client. The encryption keys never reach AWS — objects are encrypted in your application and uploaded as ciphertext.

Use cases: Regulated industries requiring end-to-end encryption, data that even AWS administrators should not be able to read, keys managed by a third-party HSM or on-premises KMS.

Access Logging and Monitoring

S3 Server Access Logging

Enable server access logging to record every request made to your bucket:

Target bucket: my-bucket-access-logs
Target prefix: my-data-bucket/

Access logs capture: requester identity, bucket name, request time, action, response status, and error code. These logs are essential for security investigations and compliance audits.

Important: Store access logs in a separate bucket (not the same bucket being logged) to prevent recursive logging. Apply a lifecycle policy to the log bucket to manage storage costs.

CloudTrail Data Events

For higher-fidelity logging, enable CloudTrail data events for S3:

  • Records API-level detail (GetObject, PutObject, DeleteObject) with full request context
  • Integrates with CloudWatch for real-time alerting
  • More expensive than server access logging ($0.10 per 100,000 events) but provides richer data

When to use which:

  • Server access logging — All buckets, baseline visibility, low cost
  • CloudTrail data events — Sensitive buckets, compliance requirements, incident response

GuardDuty S3 Protection

GuardDuty monitors S3 access patterns and alerts on suspicious activity:

  • Unusual API calls from known malicious IPs
  • Access from Tor exit nodes or anonymizing proxies
  • Anomalous data access patterns (unusual volume, unusual time, unusual requester)
  • Disabling of S3 security controls (BPA, encryption, logging)

GuardDuty S3 protection is enabled automatically when GuardDuty is active in your account.

Object Lock and Versioning

Versioning

Enable versioning on every production bucket. Versioning protects against accidental deletion and overwrites — you can always recover a previous version of any object.

Cost consideration: Versioning stores all previous versions, which increases storage costs. Use lifecycle rules to expire non-current versions after a defined retention period:

{
  "Rules": [
    {
      "Status": "Enabled",
      "NoncurrentVersionExpiration": {
        "NoncurrentDays": 90
      }
    }
  ]
}

Object Lock

Object Lock provides write-once-read-many (WORM) storage for compliance requirements:

Two modes:

  • Governance mode — Prevents deletion unless the user has specific IAM permissions (s3:BypassGovernanceRetention). Allows authorized users to override the lock.
  • Compliance mode — Prevents deletion by anyone, including the root account, until the retention period expires. Cannot be overridden.

Use cases:

  • Financial record retention (SEC Rule 17a-4)
  • Healthcare data retention (HIPAA)
  • Legal hold for litigation
  • Audit log preservation

Warning: Compliance mode Object Lock is irreversible for the retention period. If you lock objects for 7 years in compliance mode, you will pay for storage for 7 years — no exceptions.

Cross-Account Access

S3 Access Points

For buckets shared across multiple accounts or applications, Access Points simplify permission management:

my-data-bucket
├── access-point: analytics-team (read-only, prefix: analytics/)
├── access-point: data-pipeline (read-write, prefix: raw/)
└── access-point: audit-team (read-only, all prefixes)

Each Access Point has its own policy, DNS name, and network controls. This is cleaner than a single bucket policy with dozens of complex statements.

VPC restriction: Access Points can be restricted to specific VPCs, preventing access from outside your network:

{
  "Condition": {
    "StringEquals": {
      "s3:AccessPointNetworkOrigin": "VPC",
      "aws:SourceVpc": "vpc-12345"
    }
  }
}

Cross-Account Best Practices

  • Use aws:PrincipalOrgID condition to restrict access to your AWS Organization
  • Prefer IAM roles with trust policies over bucket policies with account IDs
  • Use S3 Access Points instead of complex bucket policies for multi-team access
  • Never use Principal: "*" without restrictive conditions

Lifecycle Management

Lifecycle rules reduce storage costs and enforce data retention policies:

TransitionUse CaseCost Impact
Standard → Standard-IAData accessed less than once per month (30 days minimum)45% storage savings
Standard-IA → Glacier Instant RetrievalArchive with occasional fast access68% storage savings
Glacier Instant → Glacier FlexibleArchive with infrequent access (minutes to hours retrieval)80% storage savings
Glacier Flexible → Glacier Deep ArchiveLong-term archive (12 hours retrieval)95% storage savings
Expire/DeleteData past retention period100% savings

Compliance consideration: Match lifecycle rules to your data retention policy. Do not automatically delete data that has regulatory retention requirements. For compliance-critical data, use Object Lock to prevent premature deletion.

Security Auditing

AWS Config Rules

Deploy Config rules to continuously audit S3 bucket configurations:

  • s3-bucket-public-read-prohibited — Flags buckets with public read access
  • s3-bucket-public-write-prohibited — Flags buckets with public write access
  • s3-bucket-ssl-requests-only — Flags buckets without TLS enforcement
  • s3-bucket-server-side-encryption-enabled — Flags unencrypted buckets
  • s3-bucket-logging-enabled — Flags buckets without access logging
  • s3-bucket-versioning-enabled — Flags buckets without versioning

IAM Access Analyzer

IAM Access Analyzer reviews bucket policies and Access Points to identify resources shared outside your account or organization. It flags any policy that grants access to external principals — catching misconfigurations before they become breaches.

S3 Storage Lens

Storage Lens provides organization-wide visibility into S3 usage, activity, and security posture. The free tier includes 28 metrics; the advanced tier adds cost optimization and data protection metrics.

Common S3 Security Mistakes

Mistake 1: Overly Broad Bucket Policies

The most common mistake — granting s3:* or Principal: "*" when only specific actions or principals are needed. Review every bucket policy for least privilege. Use IAM Access Analyzer to identify overly permissive policies.

Mistake 2: Not Enabling Versioning

Without versioning, a single DeleteObject call permanently removes data. An attacker with write access — or a developer running the wrong script — can destroy your data with no recovery option.

Mistake 3: Ignoring Access Logs

If you do not log access, you cannot detect unauthorized access, investigate breaches, or demonstrate compliance. Enable server access logging on every bucket, and CloudTrail data events on buckets containing sensitive data.

Mistake 4: Static Credentials in Application Code

Applications accessing S3 should use IAM roles (EC2 instance profiles, Lambda execution roles, ECS task roles) — never static access keys. Static keys in code, environment variables, or configuration files are the single largest source of AWS credential compromise.

Mistake 5: No Data Classification

Not all data requires the same security controls. Classify your data and apply controls proportionally:

ClassificationControlsExample
PublicBPA exception, no encryption requiredMarketing assets, open data
InternalBPA, SSE-S3, access loggingApplication logs, non-sensitive configs
ConfidentialBPA, SSE-KMS, CloudTrail data events, versioningCustomer data, business records
RestrictedBPA, SSE-KMS with CMK, Object Lock, VPC-only accessPII, financial data, healthcare records

S3 Security Checklist

Use this checklist for every production bucket:

  • Block Public Access enabled at account level
  • Block Public Access enabled at bucket level
  • Server-side encryption (SSE-KMS for sensitive data)
  • Bucket policy follows least privilege
  • No Principal: "*" without restrictive conditions
  • Server access logging enabled
  • CloudTrail data events enabled (for sensitive buckets)
  • Versioning enabled
  • Lifecycle rules configured
  • TLS-only access enforced
  • Cross-account access restricted to organization
  • AWS Config rules deployed for continuous monitoring

Getting Started

S3 security is not a one-time configuration — it requires continuous monitoring, policy review, and posture management as your organization grows. For a comprehensive security assessment of your AWS environment, including S3 bucket auditing, or for ongoing security management through our managed services, talk to our team.

Contact us to secure your AWS environment →

Ready to discuss your AWS strategy?

Our certified architects can help you implement these solutions.

Recommended Reading

Explore All Articles »
AWS IAM Best Practices: Least Privilege Access Control

AWS IAM Best Practices: Least Privilege Access Control

A practical guide to AWS IAM — least privilege policies, IAM roles vs users, permission boundaries, SCPs, identity federation, and the access control patterns that secure production workloads without slowing teams down.