Back to Checks
aws

S3 bucket policy denies requests over insecure transport

s3_bucket_secure_transport_policy
Service: s3Severity: medium
OfficialBuilt-inVerified
Categories:encryption
Resource Type:AwsS3Bucket

Amazon S3 buckets are evaluated for a bucket policy that enforces secure transport by denying requests when aws:SecureTransport is false.

Buckets without this explicit denial, or without a policy, are treated as allowing access over insecure transport.

Risk

HTTP access exposes object data and auth details to eavesdropping and man-in-the-middle attacks. Captured pre-signed URLs can be replayed to exfiltrate data. Traffic can be intercepted or altered, undermining confidentiality and integrity of S3 content.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks s3_bucket_secure_transport_policy

Recommendation

Enforce HTTPS-only access with a bucket policy that denies requests when aws:SecureTransport=false.

Prefer private access (VPC endpoints or CloudFront with TLS), avoid S3 website endpoints, apply least privilege, use short-lived HTTPS pre-signed URLs, and monitor logs for insecure access attempts.

Remediation

CLI

aws s3api put-bucket-policy --bucket <example_resource_name> --policy '{"Version":"2012-10-17","Statement":[{"Effect":"Deny","Principal":"*","Action":"s3:*","Resource":"arn:aws:s3:::<example_resource_name>/*","Condition":{"Bool":{"aws:SecureTransport":"false"}}}]}'

Terraform

# Deny non-SSL (HTTP) requests to the S3 bucket
resource "aws_s3_bucket_policy" "policy" {
  bucket = "<example_resource_name>"
  policy = jsonencode({
    Version   = "2012-10-17"
    Statement = [{
      Effect    = "Deny"
      Principal = "*"
      Action    = "s3:*"
      Resource  = "arn:aws:s3:::<example_resource_name>/*"
      Condition = {
        Bool = {
          "aws:SecureTransport" = "false" # Critical: deny requests not using SSL/TLS
        }
      }
    }]
  })
}

NativeIaC

# CloudFormation: Deny non-SSL (HTTP) requests to the S3 bucket
Resources:
  BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: <example_resource_name>
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Deny
            Principal: "*"
            Action: s3:*
            Resource: arn:aws:s3:::<example_resource_name>/*
            Condition:
              Bool:
                aws:SecureTransport: "false"  # Critical: deny requests not using SSL/TLS

Other

1In the AWS Console, go to S3 and open the bucket <example_resource_name>
2Select the Permissions tab and click Edit in Bucket policy
3Paste this policy, replacing the bucket name:
4```
5{
6"Version": "2012-10-17",
7"Statement": [
8{
9"Effect": "Deny",
10"Principal": "*",
11"Action": "s3:*",
12"Resource": "arn:aws:s3:::<example_resource_name>/*",
13"Condition": { "Bool": { "aws:SecureTransport": "false" } }
14}
15]
16}
17```
18Click Save changes

Check Code

from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.s3.s3_client import s3_client


class s3_bucket_secure_transport_policy(Check):
    def execute(self):
        findings = []
        for bucket in s3_client.buckets.values():
            report = Check_Report_AWS(metadata=self.metadata(), resource=bucket)
            # Check if bucket policy enforces SSL
            if not bucket.policy:
                report.status = "FAIL"
                report.status_extended = f"S3 Bucket {bucket.name} does not have a bucket policy, thus it allows HTTP requests."
            else:
                report.status = "FAIL"
                report.status_extended = f"S3 Bucket {bucket.name} allows requests over insecure transport in the bucket policy."
                for statement in bucket.policy["Statement"]:
                    if (
                        statement["Effect"] == "Deny"
                        and "Condition" in statement
                        and "Action" in statement
                        and (
                            "s3:PutObject" in statement["Action"]
                            or "*" in statement["Action"]
                            or "s3:*" in statement["Action"]
                        )
                    ):
                        if "Bool" in statement["Condition"]:
                            if "aws:SecureTransport" in statement["Condition"]["Bool"]:
                                if (
                                    statement["Condition"]["Bool"][
                                        "aws:SecureTransport"
                                    ]
                                    == "false"
                                ):
                                    report.status = "PASS"
                                    report.status_extended = f"S3 Bucket {bucket.name} has a bucket policy to deny requests over insecure transport."

            findings.append(report)
        return findings