S3 bucket policy denies requests over insecure transport
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 Cloudprowler aws --checks s3_bucket_secure_transport_policyRecommendation
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/TLSOther
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