S3 buckets should have static website hosting disabled
When you enable static website hosting on an S3 bucket, AWS creates a public HTTP endpoint (e.g., <bucket>.s3-website-<region>.amazonaws.com) that serves objects directly. This endpoint does not support HTTPS, and making it functional usually requires granting public read access through bucket policies or ACLs. Even if the original intent was to serve a few static assets, the entire bucket becomes a target for enumeration.
CloudFront with an origin access control is the right approach for serving static content from S3. It keeps the bucket private, supports HTTPS, and gives you caching and WAF integration without exposing raw S3 endpoints.
Retrofit consideration
Buckets currently serving static websites need migration to CloudFront with origin access control before the website configuration can be removed. Removing the configuration immediately breaks any DNS or application references pointing to the S3 website endpoint.
Implementation
Choose the approach that matches how you manage Terraform.
If you use terraform-aws-modules/s3-bucket/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 "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
Use AWS provider resources directly. See docs for the resources involved: aws_s3_bucket_website_configuration.
resource "aws_s3_bucket" "this" {
bucket = "pofix-abc123"
force_destroy = true
}
resource "aws_s3_bucket_website_configuration" "this" {
bucket = "example-bucket-abc123"
}
What this control checks
This control checks that no aws_s3_bucket_website_configuration resource exists for a given S3 bucket. In the current AWS provider, static website hosting uses the standalone aws_s3_bucket_website_configuration resource with nested blocks: index_document, error_document, redirect_all_requests_to, and routing_rule. A bucket passes when no such resource references it. It fails if any aws_s3_bucket_website_configuration resource exists, regardless of which documents or routing rules are configured. For buckets still using the older inline website block on aws_s3_bucket, the same applies: any website configuration present means the bucket fails.
Common pitfalls
Deprecated inline website block still enables hosting
The legacy
websiteblock insideaws_s3_bucketstill enables static website hosting, and upgrading to provider v4+ does not remove it automatically. If your Terraform was written against the old provider and you have not explicitly removed that block, the bucket has website hosting enabled regardless of what else you have configured. Remove the inlinewebsiteblock and confirm noaws_s3_bucket_website_configurationresource replaces it.Removing website config breaks existing references
The S3 website endpoint (
<bucket>.s3-website-<region>.amazonaws.com) is different from the standard S3 REST endpoint. If Route 53 alias records, CloudFront origins, or application code reference the website endpoint, removing theaws_s3_bucket_website_configurationresource causes those references to return errors. Migrate consumers to the REST endpoint or a CloudFront distribution before removing the configuration.Terraform import can reintroduce website config
Running
terraform import aws_s3_bucket_website_configuration.<name> <bucket>on a bucket that already has website hosting enabled pulls that configuration into state. If someone imports it to 'manage' the existing setup without realizing this control forbids it, the bucket stays non-compliant and the import itself is the problem.redirect_all_requests_to still counts as website hosting
Using
aws_s3_bucket_website_configurationsolely forredirect_all_requests_to(domain redirect use cases) does not exempt a bucket from this control. The S3 website endpoint is active regardless of whether any objects are being served. The bucket fails.
Audit evidence
An auditor expects evidence that no S3 buckets in the account have static website hosting enabled. AWS Config rule results for s3-bucket-website-disabled provide continuous evaluation. Alternatively, aws s3api get-bucket-website --bucket <name> returning NoSuchWebsiteConfiguration for each bucket demonstrates compliance. Screenshots from the S3 console showing 'Static website hosting' set to 'Disabled' under the Properties tab are acceptable point-in-time evidence.
For accounts with many buckets, a consolidated report from AWS Security Hub or a CSPM tool listing each bucket's website hosting status is more practical and auditable than individual screenshots.
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
s3_bucket_static_website_hosting_disabledPowerpipe Control:
aws_compliance.control.s3_bucket_static_website_hosting_disabledKICS Query:
42bb6b7f-6d54-4428-b707-666f669d94fb
Last reviewed: 2026-03-09