---
title: S3 bucket without SSL in write actions
description: Datadog, the leading service for cloud-scale monitoring.
breadcrumbs: >-
  Docs > Datadog Security > Code Security > Infrastructure as Code (IaC)
  Security > IaC Security Rules > S3 bucket without SSL in write actions
---

# S3 bucket without SSL in write actions

{% callout %}
# Important note for users on the following Datadog sites: app.ddog-gov.com, us2.ddog-gov.com

{% alert level="danger" %}
This product is not supported for your selected [Datadog site](https://docs.datadoghq.com/getting_started/site.md). ({% placeholder "user-datadog-site-name" /%}).
{% /alert %}

{% /callout %}

## Metadata{% #metadata %}

**Id:** `cloudformation-aws-s3-bucket-without-ssl-in-write-actions` 

**Provider:** AWS

**Platform:** CloudFormation

**Severity:** Medium

**Category:** Encryption

#### Learn More{% #learn-more %}

- [Provider Reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html)

### Description{% #description %}

S3 buckets should enforce SSL/TLS for data in transit to prevent unencrypted requests from exposing sensitive data or enabling man-in-the-middle attacks.

Ensure each `AWS::S3::Bucket` has an associated `AWS::S3::BucketPolicy` whose `Properties.PolicyDocument.Statement` enforces `aws:SecureTransport`. For example, use a `Deny` statement that blocks unsafe actions (such as `s3:*` or `s3:PutObject`) when `Condition.Bool["aws:SecureTransport"]` is `false`. Alternatively, use `Allow` statements that only permit those actions when `aws:SecureTransport` is `true`.

Resources missing an `AWS::S3::BucketPolicy`, or with statements that do not include the `Condition.Bool["aws:SecureTransport"]` check (that is, do not deny unsecured requests), will be flagged.

Secure configuration example:

```yaml
MyBucketPolicy:
  Type: AWS::S3::BucketPolicy
  Properties:
    Bucket: !Ref MyBucket
    PolicyDocument:
      Statement:
        - Sid: EnforceSSL
          Effect: Deny
          Principal: "*"
          Action: "s3:*"
          Resource:
            - !Sub "arn:aws:s3:::${MyBucket}"
            - !Sub "arn:aws:s3:::${MyBucket}/*"
          Condition:
            Bool:
              aws:SecureTransport: "false"
```

## Compliant Code Examples{% #compliant-code-examples %}

```yaml
#this code is a correct code for which the query should not find any result
AWSTemplateFormatVersion: 2010-09-09
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: S3Bucket
      AccessControl: PublicRead
      WebsiteConfiguration:
        IndexDocument: index.html
        ErrorDocument: error.html
    DeletionPolicy: Retain
  BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      PolicyDocument:
        Id: MyPolicy
        Version: 2012-10-17
        Statement:
          - Sid: PublicReadForGetBucketObjects
            Effect: Allow
            Principal: '*'
            Action: 's3:GetObject'
            Resource: !Join
              - ''
              - - 'arn:aws:s3:::'
                - !Ref S3Bucket
                - /*
          - Sid: EnsureSSL
            Effect: Deny
            Principal: '*'
            Action: 's3:PutObject'
            Condition:
              Bool:
                'aws:SecureTransport': false
            Resource: !Join
              - ''
              - - 'arn:aws:s3:::'
                - !Ref S3Bucket
                - /*
      Bucket: !Ref S3Bucket
Outputs:
  WebsiteURL:
    Value: !GetAtt
      - S3Bucket
      - WebsiteURL
    Description: URL for website hosted on S3
  S3BucketSecureURL:
    Value: !Join
      - ''
      - - 'https://'
        - !GetAtt
          - S3Bucket
          - DomainName
    Description: Name of S3 bucket to hold website content
```

```yaml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  S3Bucket2:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: S3Bucket2
      AccessControl: PublicRead
      WebsiteConfiguration:
        IndexDocument: index.html
        ErrorDocument: error.html
    DeletionPolicy: Retain
  BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      PolicyDocument:
        Id: MyPolicy
        Version: 2012-10-17
        Statement:
          - Sid: EnsureSSL
            Effect: Deny
            Principal: '*'
            Action: 's3:*'
            Condition:
              Bool:
                'aws:SecureTransport': false
            Resource: !Join
              - ''
              - - 'arn:aws:s3:::'
                - !Ref S3Bucket2
                - /*
      Bucket: !Ref S3Bucket2
  S3Bucket3:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: PublicRead
      WebsiteConfiguration:
        IndexDocument: index.html
        ErrorDocument: error.html
    DeletionPolicy: Retain
  BucketPolicy2:
    Type: AWS::S3::BucketPolicy
    Properties:
      PolicyDocument:
        Id: MyPolicy2
        Version: 2012-10-17
        Statement:
          - Sid: EnsureSSL
            Effect: Deny
            Principal: '*'
            Action: 's3:*'
            Condition:
              Bool:
                'aws:SecureTransport': false
            Resource: !Join
              - ''
              - - 'arn:aws:s3:::'
                - !Ref S3Bucket3
                - /*
      Bucket: !Ref S3Bucket3
Outputs:
  WebsiteURL:
    Value: !GetAtt
      - S3Bucket2
      - WebsiteURL
    Description: URL for website hosted on S3
  S3BucketSecureURL:
    Value: !Join
      - ''
      - - 'https://'
        - !GetAtt
          - S3Bucket2
          - DomainName
    Description: Name of S3 bucket to hold website content
```

```json
{
  "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z",
  "Resources": {
    "S3Bucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "BucketName": "S3Bucket",
        "AccessControl": "PublicRead",
        "WebsiteConfiguration": {
          "IndexDocument": "index.html",
          "ErrorDocument": "error.html"
        }
      },
      "DeletionPolicy": "Retain"
    },
    "BucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": "S3Bucket",
        "PolicyDocument": {
          "Id": "MyPolicy",
          "Version": "2012-10-17T00:00:00Z",
          "Statement": [
            {
              "Sid": "PublicReadForGetBucketObjects",
              "Effect": "Allow",
              "Principal": "*",
              "Action": "s3:GetObject",
              "Resource": [
                "",
                [
                  "arn:aws:s3:::",
                  "S3Bucket",
                  "/*"
                ]
              ]
            },
            {
              "Principal": "*",
              "Action": "s3:PutObject",
              "Condition": {
                "Bool": {
                  "aws:SecureTransport": false
                }
              },
              "Resource": [
                "",
                [
                  "arn:aws:s3:::",
                  "S3Bucket",
                  "/*"
                ]
              ],
              "Sid": "EnsureSSL",
              "Effect": "Deny"
            }
          ]
        }
      }
    }
  },
  "Outputs": {
    "WebsiteURL": {
      "Value": [
        "S3Bucket",
        "WebsiteURL"
      ],
      "Description": "URL for website hosted on S3"
    },
    "S3BucketSecureURL": {
      "Description": "Name of S3 bucket to hold website content",
      "Value": [
        "",
        [
          "https://",
          [
            "S3Bucket",
            "DomainName"
          ]
        ]
      ]
    }
  }
}
```

## Non-Compliant Code Examples{% #non-compliant-code-examples %}

```yaml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: S3Bucket
      AccessControl: PublicRead
      WebsiteConfiguration:
        IndexDocument: index.html
        ErrorDocument: error.html
    DeletionPolicy: Retain
  BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      PolicyDocument:
        Id: MyPolicy
        Version: 2012-10-17
        Statement:
          - Sid: PublicReadForGetBucketObjects
            Effect: Allow
            Principal: '*'
            Action: 's3:GetObject'
            Resource: !Join
              - ''
              - - 'arn:aws:s3:::'
                - !Ref S3Bucket
                - /*
      Bucket: !Ref S3Bucket
Outputs:
  WebsiteURL:
    Value: !GetAtt
      - S3Bucket
      - WebsiteURL
    Description: URL for website hosted on S3
  S3BucketSecureURL:
    Value: !Join
      - ''
      - - 'https://'
        - !GetAtt
          - S3Bucket
          - DomainName
    Description: Name of S3 bucket to hold website content
```

```json
{
  "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z",
  "Resources": {
    "BucketPolicy": {
      "Properties": {
        "Bucket": "S3Bucket33",
        "PolicyDocument": {
          "Id": "MyPolicy",
          "Statement": {
            "Action": "s3:*",
            "Condition": {
              "Bool": {
                "aws:SecureTransport": false
              }
            },
            "Effect": "Allow",
            "Principal": "*",
            "Resource": [
              "",
              {
                "playbooks": [
                  "arn:aws:s3:::",
                  "S3Bucket3",
                  "/*"
                ]
              }
            ]
          },
          "Version": "2012-10-17"
        }
      },
      "Type": "AWS::S3::BucketPolicy"
    },
    "S3Bucket33": {
      "DeletionPolicy": "Retain",
      "Properties": {
        "BucketName": "S3Bucket33",
        "AccessControl": "PublicRead",
        "WebsiteConfiguration": {
          "ErrorDocument": "error.html",
          "IndexDocument": "index.html"
        }
      },
      "Type": "AWS::S3::Bucket"
    }
  }
}
```

```yaml
AWSTemplateFormatVersion: 2010-09-09
Resources:
  S3Bucket2:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: S3Bucket2
      AccessControl: PublicRead
      WebsiteConfiguration:
        IndexDocument: index.html
        ErrorDocument: error.html
    DeletionPolicy: Retain
  BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      PolicyDocument:
        Id: MyPolicy
        Version: 2012-10-17
        Statement:
          - Sid: EnsureSSL
            Effect: Deny
            Principal: '*'
            Action: 's3:PutObject'
            Condition:
              Bool:
                'aws:SecureTransport': true
            Resource: !Join
              - ''
              - - 'arn:aws:s3:::'
                - !Ref S3Bucket2
                - /*
      Bucket: !Ref S3Bucket2
Outputs:
  WebsiteURL:
    Value: !GetAtt
      - S3Bucket2
      - WebsiteURL
    Description: URL for website hosted on S3
  S3BucketSecureURL:
    Value: !Join
      - ''
      - - 'https://'
        - !GetAtt
          - S3Bucket2
          - DomainName
    Description: Name of S3 bucket to hold website content
```
