# S3 Bucket Not Requiring HTTPS

> Every S3 bucket accepts both HTTP and HTTPS unless its policy says otherwise. TLS enforcement takes an explicit Deny on the aws:SecureTransport condition. ZopNight parses each bucket policy for that statement, flags buckets lacking it, and abstains when the policy itself could not be read (403 or throttle).

Source: https://zop.dev/integrations/aws/recommendations/s3-bucket-not-requiring-https
Updated: 2026-08-19

---

## TLS on S3 is a policy decision, not a default

The bucket endpoints speak both protocols. Modern SDKs choose HTTPS on their own,
which lulls teams into believing transit encryption is enforced. It is merely
customary. Any curl script, legacy client or misconfigured integration can still
fetch objects over plain HTTP, and nothing in the bucket's settings will stop it
until a policy denies it. Compliance frameworks such as PCI DSS and HIPAA treat
encryption in transit as an enforcement property, and on S3 enforcement lives in
exactly one place: a Deny statement on the aws:SecureTransport condition key.

## What discovery actually parses

During discovery the bucket policy is fetched (the `s3:GetBucketPolicy` read) and
scanned for a Deny that matches aws:SecureTransport set to false. Buckets carrying
such a statement are recorded as enforcing TLS; buckets with a policy but no such
statement (or with no policy at all) are recorded as not enforcing. The rule fires
only on that recorded false. When the policy fetch failed with a 403 or a throttle,
nothing is recorded and the rule abstains: unreadable is not the same as unenforced.

## Test a bucket in seconds

```bash
aws s3api get-bucket-policy --bucket my-bucket \
  --query Policy --output text | grep -c SecureTransport
```

A count of 0, or a NoSuchBucketPolicy error, means no enforcement statement
exists: this finding, reproduced.

## The statement to add

```json
{
  "Effect": "Deny",
  "Principal": "*",
  "Action": "s3:*",
  "Resource": ["arn:aws:s3:::my-bucket", "arn:aws:s3:::my-bucket/*"],
  "Condition": {"Bool": {"aws:SecureTransport": "false"}}
}
```

Deploy it after checking for HTTP-only clients: AWS SDKs are safe by default, so the
casualties are usually old custom scripts. Watch application logs for new 403s in the
first hours. That is the policy doing its job on a client someone forgot.

## Edges the rule respects

Zero dollar impact is claimed; this is transit-security posture. The rule does not
probe the endpoint over HTTP itself, does not evaluate encryption at rest (a separate
rule covers unencrypted storage), and stays silent on buckets whose policies it could
not read rather than raising false alarms on locked-down accounts.
