Skip to main content
emnode
Compliance High severity

AWS Security Hub · CloudFront

CloudFront.12: A distribution points at a non-existent S3 origin (takeover risk)

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub CloudFront.12 check?

CloudFront.12 checks whether a distribution's S3 origin points to a bucket that still exists. It reports FAILED when the referenced bucket is gone: a periodic check that catches origins left dangling long after the distribution last changed. It scopes to plain S3 REST-endpoint origins, not buckets configured for static website hosting.

Why does CloudFront.12 matter?

S3 bucket names are globally unique and released back to the pool the moment a bucket is deleted. An attacker who re-creates the orphaned name in their own account now controls what your distribution serves on your trusted domain (your URL, your TLS certificate, your brand), hosting a phishing page, defacement, or malware. The takeover is silent and trivially automated, which is why it's rated High.

How do I fix CloudFront.12?

  1. Confirm the origin is genuinely dangling: extract the bucket name and run `aws s3api head-bucket --bucket <name>`. A 404 is the failing condition, a 403 means it exists but you may not own it.
  2. Close the exposure immediately: if the distribution must stay, re-create the bucket under your own account to reclaim the name; otherwise remove the dangling origin or disable and delete the distribution.
  3. If repointing, update the origin `DomainName` to the correct bucket via the ETag-guarded `update-distribution` flow and re-attach origin access control.
  4. Keep the `cloudfront-s3-origin-non-existent-bucket` Config rule enabled and order teardown so deleting a bucket can't leave a live origin pointing at nothing.

Remediation script · bash

# 1. Lock an S3 origin: only THIS distribution may read the bucket.
cat > bucket-policy.json <<'JSON'
{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "AllowCloudFrontServicePrincipalReadOnly",
    "Effect": "Allow",
    "Principal": { "Service": "cloudfront.amazonaws.com" },
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::my-downloads-bucket/*",
    "Condition": { "StringEquals": {
      "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/E2QWRUHAPOMQZL"
    } }
  }]
}
JSON
aws s3api put-bucket-policy --bucket my-downloads-bucket --policy file://bucket-policy.json

# 2. Raise the minimum TLS version (the field is nested in ViewerCertificate, so send the whole config back).
aws cloudfront get-distribution-config --id E2QWRUHAPOMQZL > dist.json
ETAG=$(python3 -c "import json;print(json.load(open('dist.json'))['ETag'])")
# ... edit dist.json: ViewerCertificate.MinimumProtocolVersion = TLSv1.2_2021, ViewerProtocolPolicy = redirect-to-https ...
aws cloudfront update-distribution --id E2QWRUHAPOMQZL \
  --distribution-config file://distribution-config.json --if-match "$ETAG"

# 3. Confirm the second door is shut: a raw S3 GET should now return 403.
curl -s -o /dev/null -w '%{http_code}\n' https://my-downloads-bucket.s3.amazonaws.com/file.pdf

Full walkthrough (console steps, edge cases and verification) in the lesson Protect CloudFront distributions and origins.

Is CloudFront.12 a false positive?

A cross-account S3 origin can look dangling when it isn't. If the bucket lives in a different account that you also own, `head-bucket` from the distribution's account returns a 403 rather than a 200: the bucket exists and you control it, but the caller can't see it, which is exactly the case the remediation flags as "exists, may not be yours." The control's own scope also narrows what's in play: it only evaluates plain S3 REST-endpoint origins, so a bucket configured for static website hosting (a custom-origin domain) is out of scope by design and won't trigger this. Before treating a finding as a real takeover risk, confirm ownership of the named bucket; if it's a legitimately owned cross-account origin, document that ownership and suppress the finding rather than re-creating a bucket you already control.

Part of the learning path Lock down access