Skip to main content

S3 Bucket Secure Transport Policy

Overview

This check verifies that your Amazon S3 buckets require encrypted (HTTPS) connections. Without this policy, data can be transferred over unencrypted HTTP connections, which is a security risk.

Risk

When S3 buckets allow HTTP access:

  • Data exposure: Information sent over HTTP can be intercepted by attackers ("man-in-the-middle" attacks)
  • Credential theft: Authentication tokens and pre-signed URLs can be stolen
  • Compliance violations: Many regulations (PCI-DSS, HIPAA, SOC 2) require encryption in transit

Remediation Steps

Prerequisites

You need permission to modify S3 bucket policies. If you are not a bucket owner or administrator, contact someone who can make these changes.

Required IAM permissions

Your IAM user or role needs the s3:PutBucketPolicy and s3:GetBucketPolicy permissions on the target bucket.

Example IAM policy:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketPolicy",
"s3:PutBucketPolicy"
],
"Resource": "arn:aws:s3:::<your-bucket-name>"
}
]
}

AWS Console Method

  1. Open the Amazon S3 console
  2. Click on the bucket name you want to secure
  3. Go to the Permissions tab
  4. Scroll down to Bucket policy and click Edit
  5. Add the following policy (replace <your-bucket-name> with your actual bucket name):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyInsecureTransport",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::<your-bucket-name>",
"arn:aws:s3:::<your-bucket-name>/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}
]
}
  1. Click Save changes

Important: If the bucket already has a policy, add this statement to the existing Statement array rather than replacing the entire policy.

AWS CLI (optional)

Apply policy to a bucket

For a bucket with no existing policy:

aws s3api put-bucket-policy \
--bucket <your-bucket-name> \
--region us-east-1 \
--policy '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyInsecureTransport",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::<your-bucket-name>",
"arn:aws:s3:::<your-bucket-name>/*"
],
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
}
}
]
}'

For a bucket with an existing policy:

First, retrieve the current policy:

aws s3api get-bucket-policy \
--bucket <your-bucket-name> \
--region us-east-1 \
--query Policy \
--output text > current-policy.json

Edit current-policy.json to add the DenyInsecureTransport statement to the existing Statement array, then apply:

aws s3api put-bucket-policy \
--bucket <your-bucket-name> \
--region us-east-1 \
--policy file://current-policy.json
CloudFormation (optional)

Use this template to create a new S3 bucket with secure transport enforced:

AWSTemplateFormatVersion: '2010-09-09'
Description: S3 bucket with secure transport policy enforcing HTTPS-only access

Parameters:
BucketName:
Type: String
Description: Name of the S3 bucket to create

Resources:
SecureS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName

SecureTransportPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref SecureS3Bucket
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: DenyInsecureTransport
Effect: Deny
Principal: '*'
Action: 's3:*'
Resource:
- !Sub 'arn:aws:s3:::${SecureS3Bucket}'
- !Sub 'arn:aws:s3:::${SecureS3Bucket}/*'
Condition:
Bool:
'aws:SecureTransport': 'false'

Outputs:
BucketName:
Description: Name of the created S3 bucket
Value: !Ref SecureS3Bucket
BucketArn:
Description: ARN of the created S3 bucket
Value: !GetAtt SecureS3Bucket.Arn

Deploy the stack:

aws cloudformation create-stack \
--stack-name secure-s3-bucket \
--template-body file://template.yaml \
--parameters ParameterKey=BucketName,ParameterValue=<your-bucket-name> \
--region us-east-1
Terraform (optional)
variable "bucket_name" {
description = "Name of the S3 bucket"
type = string
}

resource "aws_s3_bucket" "secure_bucket" {
bucket = var.bucket_name
}

resource "aws_s3_bucket_policy" "secure_transport" {
bucket = aws_s3_bucket.secure_bucket.id

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "DenyInsecureTransport"
Effect = "Deny"
Principal = "*"
Action = "s3:*"
Resource = [
aws_s3_bucket.secure_bucket.arn,
"${aws_s3_bucket.secure_bucket.arn}/*"
]
Condition = {
Bool = {
"aws:SecureTransport" = "false"
}
}
}
]
})
}

output "bucket_name" {
description = "Name of the S3 bucket"
value = aws_s3_bucket.secure_bucket.id
}

output "bucket_arn" {
description = "ARN of the S3 bucket"
value = aws_s3_bucket.secure_bucket.arn
}

Apply the configuration:

terraform init
terraform plan -var="bucket_name=<your-bucket-name>"
terraform apply -var="bucket_name=<your-bucket-name>"

Verification

After applying the policy, verify it is in place:

  1. In the S3 console, go to your bucket and click the Permissions tab
  2. Under Bucket policy, confirm you see the DenyInsecureTransport statement
  3. The aws:SecureTransport condition should be set to deny when false
CLI verification
aws s3api get-bucket-policy \
--bucket <your-bucket-name> \
--region us-east-1 \
--query Policy \
--output text | jq .

Look for a statement with:

  • "Effect": "Deny"
  • "Condition": { "Bool": { "aws:SecureTransport": "false" } }

Test the policy (optional):

# This should fail with "Access Denied" because it uses HTTP
curl "http://<your-bucket-name>.s3.us-east-1.amazonaws.com/test-file.txt"

# This should work (if the file exists and you have access)
curl "https://<your-bucket-name>.s3.us-east-1.amazonaws.com/test-file.txt"

Additional Resources

Notes

  • Existing policies: If your bucket already has a policy, merge the new statement with existing ones. Replacing the entire policy will remove any other permissions you have set.

  • Application compatibility: Before applying this policy, ensure all applications accessing the bucket use HTTPS. Applications using HTTP will immediately lose access.

  • Pre-signed URLs: This policy also affects pre-signed URLs. Any pre-signed URLs generated must use HTTPS to work.

  • CloudFront integration: If you use CloudFront in front of S3, ensure your CloudFront distribution is configured to use HTTPS when communicating with the S3 origin.

  • VPC endpoints: If accessing S3 through a VPC endpoint, traffic is already encrypted within AWS infrastructure, but applying this policy is still recommended for defense-in-depth.