AWS Security Hub · CloudFront
CloudFront.6: Distributions should have WAF enabled
Written and reviewed by Emnode · Last reviewed
What does AWS Security Hub CloudFront.6 check?
CloudFront.6 checks whether a distribution is associated with a web ACL, from either AWS WAF (WAFv2) or the older WAF Classic. It reports FAILED when the distribution's `WebACLId` is empty. The check is binary: it confirms a firewall is in the request path, not that the rules are any good.
Why does CloudFront.6 matter?
An unprotected distribution forwards every request straight to your origin: SQL-injection and XSS probes, vulnerability scanners, and credential-stuffing runs against login endpoints. Layer 7 floods sail through to exhaust origin compute and database connections, and you pay CloudFront request and egress charges to serve all of it. It maps to PCI DSS 6.4.2 (a WAF in front of public-facing apps).
How do I fix CloudFront.6?
- List distributions and read `WebACLId`; triage internet-facing ones with an empty value first.
- Create a WAFv2 web ACL in the global CLOUDFRONT scope (managed from us-east-1) with the AWS-managed common and known-bad-inputs rule groups plus a rate-based rule.
- Associate it with `aws wafv2 associate-web-acl`, wait for the edge to propagate, and confirm `WebACLId` is now populated.
- Bake a baseline web ACL into the distribution IaC template so new distributions ship protected by default.
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.6 a false positive?
The control evaluates only the presence of an association, not enforcement: a web ACL running entirely in Count mode still passes CloudFront.6, which can give a false sense of protection.
More CloudFront controls
- CloudFront.1 No default root object, exposing the distribution listing
- CloudFront.3 Distributions should require encryption in transit
- CloudFront.5 Distributions should have logging enabled
- CloudFront.9 Distributions should encrypt traffic to custom origins
- CloudFront.10 No deprecated SSL protocols to custom origins
- CloudFront.12 A distribution points at a non-existent S3 origin (takeover risk)
- CloudFront.13 Distributions should use origin access control
- CloudFront.15 Distributions should use recommended TLS policy
- CloudFront.16 OAC for Lambda function URL origins
- CloudFront.17 Use trusted key groups for signed URLs/cookies