S3 bucket has static website hosting configured

Operate an S3 website with deliberate content exposure and transport-protection requirements.

Description

S3 static website hosting is a legitimate way to serve public content. WebsiteConfiguration does not itself grant object-read permission, but objects served through the website endpoint must be publicly readable. The S3 website endpoint itself does not support HTTPS.

Potential impact

  • Configuration files or backups accidentally included in the public-read scope can disclose unintended information.
  • Content served directly over HTTP lacks TLS protection in transit. Changing the stored content would require separate write access or another compromise path.

Remediation

  • Remove unnecessary website configuration and public grants, and enable Block Public Access.
  • If the website is needed, separate public files and restrict deployment permissions and read scope. Do not include sensitive files or secrets.
  • For HTTPS with a private origin, consider a regular S3 REST origin with CloudFront origin access control (OAC). An S3 website endpoint is a custom origin in CloudFront and cannot use OAC.

Examples

The first example uses a policy to make website objects publicly readable. Actual service also requires uploaded content; account-level public-access protection may reject the policy. The revision is for a website that is no longer needed. Prepare an alternative delivery path before interrupting an active service.

Before

yaml
Resources:
  Bucket2:
    Type: AWS::S3::Bucket
    Properties:
      OwnershipControls:
        Rules:
          - ObjectOwnership: BucketOwnerEnforced
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: false
        IgnorePublicAcls: true
        RestrictPublicBuckets: false
      WebsiteConfiguration:
        IndexDocument: index.html
        ErrorDocument: error.html
  WebsiteReadPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref Bucket2
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal: '*'
            Action: s3:GetObject
            Resource: !Sub '${Bucket2.Arn}/*'

ACLs are disabled and the policy grants public object reads. Deploy only files intended for public distribution to this bucket.

After

yaml
Resources:
  Bucket2:
    Type: AWS::S3::Bucket
    Properties:
      OwnershipControls:
        Rules:
          - ObjectOwnership: BucketOwnerEnforced
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

The website configuration and public-read policy are removed while all four blocking options are enabled on the same bucket. This change does not configure a replacement HTTPS website.

References