CloudFront distributions should have a default root object configured
Without a default root object, requests to the root of your CloudFront distribution (e.g., https://d111111abcdef8.cloudfront.net/) go straight to the origin's root path. Depending on origin configuration, this can return error messages or unintended responses that expose implementation details, S3 bucket structure, or server internals.
Setting default_root_object to something like index.html gives you explicit control over what visitors see at the root path.
Implementation
Choose the approach that matches how you manage Terraform.
Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.
module "cloudfront" {
source = "nistcsfv11.compliance.tf/terraform-aws-modules/cloudfront/aws"
version = ">=6.0.0,<7.0.0"
}
If you use terraform-aws-modules/cloudfront/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.
module "cloudfront" {
source = "terraform-aws-modules/cloudfront/aws"
version = ">=6.0.0,<7.0.0"
}
Use AWS provider resources directly. See docs for the resources involved: aws_cloudfront_distribution.
resource "aws_cloudfront_distribution" "this" {
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
field_level_encryption_id = "abc123"
forwarded_values {
cookies {
forward = "none"
}
query_string = false
}
target_origin_id = "S3Origin"
viewer_protocol_policy = "redirect-to-https"
}
default_root_object = "index.html"
enabled = true
logging_config {
bucket = "example-bucket-abc123_domain_name"
}
origin {
domain_name = "example.s3.amazonaws.com"
origin_id = "S3Origin"
}
restrictions {
geo_restriction {
locations = ["US", "CA", "GB"]
restriction_type = "whitelist"
}
}
viewer_certificate {
acm_certificate_arn = "arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012"
minimum_protocol_version = "TLSv1.2_2021"
ssl_support_method = "sni-only"
}
wait_for_deployment = false
web_acl_id = "arn:aws:wafv2:us-east-1:123456789012:regional/webacl/example/12345678-1234-1234-1234-123456789012"
}
What this control checks
The aws_cloudfront_distribution resource must include default_root_object set to a non-empty string. "index.html" is the typical value, but any valid object key in the origin works. It fails when the argument is omitted or set to "". Note that the argument takes an object name only, not a path with a leading slash. This is a single-line change on the distribution resource with no additional resources required.
Common pitfalls
Empty string passes Terraform validation but fails the control
default_root_object = ""passes Terraform's syntax check but sets no actual default on the distribution. The compliance check fails. Set a real object key.Leading slash in the object name
Drop the leading slash. CloudFront expects
index.html, not/index.html. The API rejects or mishandles the leading slash, and Terraform itself won't catch the format error, so this tends to slip through until deployment.Default root object only applies to the root URL
default_root_objectonly affects requests to the distribution root (e.g.,https://d111.cloudfront.net/). Subdirectory requests like/blog/are unaffected. If you need default objects at subdirectory paths, that requires a CloudFront Function or Lambda@Edge, which is outside the scope of this control.
Audit evidence
Auditors expect Config rule results for cloudfront-default-root-object-configured showing all distributions as compliant. aws cloudfront list-distributions output filtered to confirm every distribution's DefaultRootObject field is populated also works. Console screenshots of each distribution's General settings are acceptable for smaller environments. Automated scan reports from Prowler or Security Hub showing this check passing across all accounts are sufficient for larger organizations.
Framework-specific interpretation
NIST Cybersecurity Framework v1.1: PR.AC and PR.DS in the CSF's Protect function both apply here. A distribution without a default root object can leak implementation details or expose origin structure at the root URL. Setting one ensures visitors get a controlled response rather than an error or unintended content that reveals how the backend is organized.
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
cloudfront_distribution_default_root_object_configuredAWS Config Managed Rule:
CLOUDFRONT_DEFAULT_ROOT_OBJECT_CONFIGUREDCheckov Check:
CKV_AWS_305Powerpipe Control:
aws_compliance.control.cloudfront_distribution_default_root_object_configuredProwler Check:
cloudfront_distributions_default_root_objectAWS Security Hub Control:
CloudFront.1
Last reviewed: 2026-03-08