---
title: S3 static website host enabled
description: Datadog, the leading service for cloud-scale monitoring.
breadcrumbs: >-
  Docs > Datadog Security > Code Security > Infrastructure as Code (IaC)
  Security > IaC Security Rules > S3 static website host enabled
---

> For the complete documentation index, see [llms.txt](https://docs.datadoghq.com/llms.txt).

# S3 static website host enabled

{% callout %}
# Important note for users on the following Datadog sites: app.ddog-gov.com, us2.ddog-gov.com

{% alert level="danger" %}
This product is not supported for your selected [Datadog site](https://docs.datadoghq.com/getting_started/site.md). ({% placeholder "user-datadog-site-name" /%}).
{% /alert %}

{% /callout %}

## Metadata{% #metadata %}

**Id:** `terraform-aws-s3-static-website-host-enabled` 

**Provider:** AWS

**Platform:** Terraform

**Severity:** High

**Category:** Insecure Configurations

#### Learn More{% #learn-more %}

- [Provider Reference](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket#website)

### Description{% #description %}

AWS S3 static website hosting allows serving content directly from buckets without additional authentication, potentially exposing sensitive data to the internet. When enabled via the `website` block, the bucket content becomes accessible through the website endpoint, bypassing S3's access controls and increasing the attack surface. Attackers could access unintended data if bucket policies are misconfigured or files are incorrectly permissioned.

Secure configuration example:

```
resource "aws_s3_bucket" "secure_example" {
  bucket = "s3-website-test.hashicorp.com"
  acl    = "public-read"
  // No website configuration block
}
```

Instead, consider using CloudFront distribution with proper access controls and HTTPS to securely serve website content.

## Compliant Code Examples{% #compliant-code-examples %}

```terraform
provider "aws" {
  region = "us-east-1"
}

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}

resource "aws_s3_bucket" "negative1" {
  bucket = "s3-website-test.hashicorp.com"
  acl    = "public-read"
}
```

```terraform
module "s3_bucket" {
  source = "terraform-aws-modules/s3-bucket/aws"
  version = "3.7.0"

  bucket = "my-s3-bucket"
  acl    = "private"

  versioning = {
    enabled = true
  }
}
```

```terraform
terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "4.2.0"
    }
  }
}

provider "aws" {
  # Configuration options
}


resource "aws_s3_bucket" "bu" {
  bucket = "my-tf-test-bucket"

  tags = {
    Name        = "My bucket"
    Environment = "Dev"
  }
}
```

## Non-Compliant Code Examples{% #non-compliant-code-examples %}

```terraform
provider "aws" {
  region = "us-east-1"
}

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}

resource "aws_s3_bucket" "positive1" {
  bucket = "s3-website-test.hashicorp.com"
  acl    = "public-read"

  website {
    index_document = "index.html"
    error_document = "error.html"
  }
}
```

```terraform
# Known gap (not enforced by positive_expected_result.json): the "after TF
# AWS 4.0" DatadogPolicy body relies on tf_lib.has_target_resource, which
# links aws_s3_bucket_website_configuration back to its bucket via
# terraform.rego's target_resource_bucket_refs -- but that only works when
# the bucket attribute is present in planned_values. Here bucket is a
# module-internal reference (aws_s3_bucket.this.id) that is genuinely
# unresolved pre-apply and only appears in
# resource_changes[].change.after_unknown, which the plan-JSON parser never
# reads. This means the rule cannot link the two resources via plan JSON for
# this fresh-create case. See query.rego and terraform.rego's
# target_resource_bucket_refs/resolve_s3_bucket_key.
module "s3_bucket" {
  source = "terraform-aws-modules/s3-bucket/aws"
  version = "3.7.0"

  bucket = "my-s3-bucket"
  acl    = "private"

  versioning = {
    enabled = true
  }

  website = {
    index_document = "index.html"
    error_document = "error.html"
  }
}
```

```terraform
terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "4.2.0"
    }
  }
}

provider "aws" {
  # Configuration options
}


resource "aws_s3_bucket" "buc" {
  bucket = "my-tf-test-bucket"

  tags = {
    Name        = "My bucket"
    Environment = "Dev"
  }
}

resource "aws_s3_bucket_website_configuration" "example" {
  bucket = aws_s3_bucket.buc.bucket

  index_document {
    suffix = "index.html"
  }

  error_document {
    key = "error.html"
  }

  routing_rule {
    condition {
      key_prefix_equals = "docs/"
    }
    redirect {
      replace_key_prefix_with = "documents/"
    }
  }
}
```
