Back to Checks
aws

CloudFront distribution S3 origins reference existing buckets

cloudfront_distributions_s3_origin_non_existent_bucket
Service: cloudfrontSeverity: high
OfficialBuilt-inVerified
Categories:resilience
Resource Type:AwsCloudFrontDistribution

CloudFront distributions with S3OriginConfig should reference existing S3 bucket origins (excluding static website hosting).

Identifies origins where the configured bucket name does not exist.

Risk

Dangling S3 origins allow potential bucket takeover: an attacker could create the missing bucket and have CloudFront retrieve attacker-controlled objects if access isn't restricted.

This threatens integrity (content spoofing, cache poisoning) and availability (errors/timeouts), undermining user trust.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks cloudfront_distributions_s3_origin_non_existent_bucket

Recommendation

Ensure origins reference valid, owned buckets; delete or update stale references. Enforce origin access control (or OAI) and tight bucket policies so only the distribution can access objects. Apply least privilege, manage bucket names, and monitor origin health to prevent misrouting.

Remediation

Terraform

# Ensure the S3 bucket referenced by the CloudFront S3 origin exists
resource "aws_s3_bucket" "<example_resource_name>" {
  bucket = "<example_resource_name>"  # Critical: must exactly match the bucket name used in the CloudFront origin's domain (before ".s3")
}

NativeIaC

# CloudFormation: ensure the S3 bucket referenced by the CloudFront S3 origin exists
Resources:
  <example_resource_name>:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: <example_resource_name>  # Critical: must exactly match the bucket name used in the CloudFront origin's domain (before ".s3") to make it exist

Other

1In the AWS console, open CloudFront and select the distribution
2Go to Origins, select the S3 origin, and note the Domain Name (the bucket name is the text before ".s3")
3Open the S3 console, click Create bucket, enter the exact bucket name from step 2, and create the bucket
4Re-run the check

Check Code

from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.cloudfront.cloudfront_client import (
    cloudfront_client,
)
from prowler.providers.aws.services.s3.s3_client import s3_client


class cloudfront_distributions_s3_origin_non_existent_bucket(Check):
    def execute(self):
        findings = []
        for distribution in cloudfront_client.distributions.values():
            report = Check_Report_AWS(metadata=self.metadata(), resource=distribution)
            report.status = "PASS"
            report.status_extended = f"CloudFront Distribution {distribution.id} does not have non-existent S3 buckets as origins."
            non_existent_buckets = []

            for origin in distribution.origins:
                if origin.s3_origin_config:
                    bucket_name = origin.domain_name.split(".s3")[0]
                    if not s3_client._head_bucket(bucket_name):
                        non_existent_buckets.append(bucket_name)

            if non_existent_buckets:
                report.status = "FAIL"
                report.status_extended = f"CloudFront Distribution {distribution.id} has non-existent S3 buckets as origins: {','.join(non_existent_buckets)}."

            findings.append(report)

        return findings