Sachith Dassanayake Software Engineering S3/CloudFront secure patterns — Production Hardening — Practical Guide (Nov 23, 2025)

S3/CloudFront secure patterns — Production Hardening — Practical Guide (Nov 23, 2025)

S3/CloudFront secure patterns — Production Hardening — Practical Guide (Nov 23, 2025)

S3/CloudFront secure patterns — Production Hardening

S3/CloudFront secure patterns — Production Hardening

Level: Experienced

As of November 23, 2025

Amazon S3 combined with Amazon CloudFront (AWS’s CDN) is a foundational pattern for serving web content at scale. However, securing this duo in production requires careful design beyond default settings, particularly as modern attacks and compliance requirements escalate. This article focuses on robust, production-hardened practices for S3/CloudFront setups, mainly aligned to AWS SDK and Console behaviours as of late 2025.

Prerequisites

  • Familiarity with AWS IAM roles and policies
  • Experience with Amazon S3 bucket policies and ACLs
  • Basic understanding of CloudFront distributions and behaviours
  • AWS CLI version 2.x or Console access with comprehensive admin permissions
  • Understanding of TLS, HTTP headers, and CDN caching strategies

Security features evolve continuously. This guide refers to stable, broadly-available features as of AWS SDKs and Console updates through late 2025. Some preview or region-limited features are noted but separated.

Hands-on steps

1. Lock down S3 buckets to CloudFront using Origin Access Control (OAC)

Previously, Origin Access Identity (OAI) was used to restrict direct S3 access to CloudFront. Since mid-2023, AWS recommends Origin Access Control (OAC) for modern, secure, and more manageable origin authentication.

Create an OAC, assign it to your CloudFront distribution’s S3 origin, then restrict bucket policy access only to that OAC. This prevents direct public or unauthorised access to S3 objects and ensures traffic flows solely through CloudFront.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudFrontServicePrincipalReadOnly",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudfront.amazonaws.com"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::your-bucket-name/*",
      "Condition": {
        "StringEquals": {
          "AWS:SourceArn": "arn:aws:cloudfront::your-account-id:distribution/your-distribution-id"
        }
      }
    }
  ]
}

Note: When using OAC, the signed header uses signature version 4, and access is controlled via the Origin-Access-Control header.

2. Enforce HTTPS-only access

Both for client connections and for origin fetches, enforce HTTPS-only.

  • Set Viewer Protocol Policy in CloudFront behaviours to Redirect HTTP to HTTPS or HTTPS Only.
  • Configure the S3 origin in CloudFront to use HTTPS endpoints (use S3 standard endpoint with HTTPS).
  • Ensure your CloudFront distribution enforces minimum TLS version 1.2 or above.

This prevents downgrade attacks and ensures data confidentiality in transit.

3. Use strict cache and security headers

Implement and inject HTTP security headers via CloudFront Functions or Lambda@Edge:

  • Strict-Transport-Security (HSTS) with a long max-age
  • Content-Security-Policy (CSP) tailored to your application
  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY or SAMEORIGIN
  • Referrer-Policy as per your privacy needs
// Example CloudFront Function adding security headers
function handler(event) {
  var response = event.response;
  var headers = response.headers;

  headers['strict-transport-security'] = { value: 'max-age=63072000; includeSubDomains; preload' };
  headers['content-security-policy'] = { value: "default-src 'self'; img-src https: data:;" };
  headers['x-content-type-options'] = { value: 'nosniff' };
  headers['x-frame-options'] = { value: 'DENY' };
  headers['referrer-policy'] = { value: 'no-referrer-when-downgrade' };

  return response;
}

4. Protect against public listing and restrict bucket policies

Ensure S3 buckets have the Block Public Access settings enabled to prevent public list or upload:

  • Block new public ACLs and policies
  • Remove existing public permissions
  • Disable any ACL-based public permissions where possible, preferring bucket policies over ACLs

Avoid overly permissive bucket policies like "Principal": "*" with s3:GetObject.

5. Use Origin Request Policies to forward only necessary headers and cookies

Minimise data leakage and reduce cache fragmentation by forwarding only essential headers, cookies, and query strings to S3:

  • Create an Origin Request Policy specifying minimal headers
  • Link it to the CloudFront behaviour
  • Avoid forwarding Authorization headers unless required

This practice helps prevent unintended credential exposure and improves cache hit ratio.

6. Enable AWS WAF or other Web Application Firewalls

Deploy AWS WAF to mitigate common attacks (SQL injection, XSS, request anomalies). Attach WAF to CloudFront to filter inbound traffic before it reaches S3.

Use managed rule groups by AWS or third-party vendors, and add custom rules as per your threat model.

Common pitfalls

  • Misconfigured bucket policies allowing wider-than-intended access, especially Origin Access Identity usage that is now deprecated in favour of OAC.
  • Inadequate HTTPS enforcement leading to mixed content warnings or potential downgrade attacks.
  • Over-forwarding headers and cookies causing cache inefficiencies or unintended information leaks.
  • Failure to remove or block public access especially when migrating legacy buckets.
  • Insufficient logging and monitoring at both S3 and CloudFront layers.
  • Neglecting WAF or firewall configuration leaving endpoints vulnerable to common attack classes.

Validation

  • Test URLs with curl -I https://your-cloudfront-url to confirm security headers exist, HTTPS enforced, and no open redirects.
  • Use AWS CLI to test S3 access directly:
    aws s3api get-object --bucket your-bucket-name --key some-key.txt out.txt

    This command should fail with access denied if OAC and policies are correct.

  • CloudFront cache and behaviour can be validated via CloudFront console logs and AWS CloudWatch metrics.
  • Simulate a public bucket test from a non-privileged network – direct S3 URL should not be accessible.
  • Verify WAF rule matches and logging through AWS WAF consoles.

Checklist / TL;DR

  • Use Origin Access Control (OAC) instead of deprecated OAI for CloudFront–S3 lock-down.
  • Enforce HTTPS everywhere—viewer protocol and origin HTTPS only.
  • Add strict HTTP security headers using CloudFront Functions or Lambda@Edge.
  • Enable and configure Block Public Access on all S3 buckets.
  • Restrict origin requests to forwarding minimal headers, cookies, and query strings.
  • Protect via AWS WAF with managed and custom rules.
  • Regularly review and audit your bucket policies, distribution settings, and logs.
  • Validate setup with direct S3 access tests and HTTP response inspections.

References

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Related Post