This check flags CloudTrail log buckets that do not have S3 Block Public Access fully enabled. Your audit trail is one of the most sensitive datasets in your account, so lock it down by turning on all four Block Public Access settings at the bucket and account level.
CloudTrail is the system of record for everything that happens in your AWS account. Every API call, every console login, every IAM change ends up as a log event, and by default those events land in an S3 bucket. If that bucket can be reached by anyone on the internet, you have handed an attacker a detailed map of your environment, plus the exact thing they need to cover their tracks.
The account_cloudtrailbucketpublic check looks at the S3 bucket receiving your CloudTrail logs and verifies that public access is explicitly blocked. If Block Public Access is not enabled, the bucket is flagged, even if no public bucket policy currently exists.
What this check detects
The check inspects the S3 bucket configured as the destination for one or more CloudTrail trails and confirms that the bucket has S3 Block Public Access turned on. Specifically, it looks for the four Block Public Access controls being set to true:
- BlockPublicAcls — rejects new public ACLs on the bucket and objects
- IgnorePublicAcls — ignores any public ACLs that already exist
- BlockPublicPolicy — rejects bucket policies that grant public access
- RestrictPublicBuckets — restricts access to the bucket from non-account principals
If any of these are missing or set to false, the bucket is considered potentially public and the check fails.
Note: A bucket can fail this check even when it has no public bucket policy today. The point is that nothing prevents one from being added tomorrow. Block Public Access is a guardrail, not a reaction to an existing exposure.
Why it matters
CloudTrail logs are not just operational noise. They contain a precise inventory of your account: which services you run, which IAM principals exist, what regions are active, source IP addresses, user agents, and the timing of sensitive operations. That is reconnaissance gold.
Here is how a publicly accessible CloudTrail bucket plays out in a real incident:
- Discovery. An attacker enumerates S3 bucket names. CloudTrail buckets often follow predictable naming like
aws-cloudtrail-logs-123456789012-abcdeforcompany-cloudtrail. - Reconnaissance. With read access, they pull months of logs and learn your account structure, your privileged roles, and your normal patterns of activity.
- Cover-up. If the bucket also allows public writes or deletes, an attacker who has already gained a foothold can tamper with or delete log objects to erase evidence of the intrusion.
The business impact is twofold. First, you leak operational intelligence that lowers the cost of attacking you. Second, you risk losing the audit trail you need for incident response and compliance frameworks like SOC 2, PCI DSS, and HIPAA, all of which expect tamper-resistant logging.
Warning: A leaked CloudTrail history can expose details about resources you have since decommissioned. Even if you fix the bucket today, assume anything previously readable while it was open has already been copied.
How to fix it
The fix is straightforward: enable all four Block Public Access settings on the bucket. You should also confirm the account-level Block Public Access is on so future buckets inherit the protection.
Step 1: Find the CloudTrail bucket
aws cloudtrail describe-trails \
--query 'trailList[].{Name:Name,Bucket:S3BucketName}' \
--output table
Step 2: Check the current Block Public Access state
aws s3api get-public-access-block \
--bucket aws-cloudtrail-logs-123456789012-abcdef
If the command returns an error saying no configuration is found, that confirms the bucket has no Block Public Access settings at all.
Step 3: Enable Block Public Access on the bucket
Danger: Confirm that no legitimate workflow relies on public access to this bucket before applying. CloudTrail buckets should never be public, but if some downstream tool was misconfigured to read it anonymously, that tool will break. Fix the tool to use IAM credentials, do not leave the bucket open.
aws s3api put-public-access-block \
--bucket aws-cloudtrail-logs-123456789012-abcdef \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
Step 4: Enable Block Public Access at the account level
This is the belt-and-suspenders move. It blocks public access across every bucket in the account, including future ones.
aws s3control put-public-access-block \
--account-id 123456789012 \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
Console steps
- Open the S3 console and select the CloudTrail bucket.
- Go to the Permissions tab.
- Under Block public access (bucket settings), click Edit.
- Check Block all public access and save, confirming when prompted.
Tip: While you are in the bucket settings, verify that the bucket policy restricts access to the CloudTrail service principal and your own account only, and that S3 Object Lock or a strict deny-on-delete policy is in place to make logs tamper-resistant.
Fixing it with Infrastructure as Code
If you manage CloudTrail in Terraform, attach a dedicated Block Public Access resource to the log bucket so the setting is enforced on every apply.
resource "aws_s3_bucket" "cloudtrail" {
bucket = "aws-cloudtrail-logs-123456789012-abcdef"
}
resource "aws_s3_bucket_public_access_block" "cloudtrail" {
bucket = aws_s3_bucket.cloudtrail.id
block_public_acls = true
ignore_public_acls = true
block_public_policy = true
restrict_public_buckets = true
}
For CloudFormation, set the same controls on the bucket definition:
CloudTrailBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: aws-cloudtrail-logs-123456789012-abcdef
PublicAccessBlockConfiguration:
BlockPublicAcls: true
IgnorePublicAcls: true
BlockPublicPolicy: true
RestrictPublicBuckets: true
How to prevent it from happening again
Manual fixes drift. The goal is to make a public CloudTrail bucket impossible to create in the first place.
Enforce account-level Block Public Access
The account-level setting from Step 4 is the single most effective preventive control. Once it is on, S3 ignores public ACLs and rejects public policies for all current and future buckets, so a misconfiguration cannot accidentally open the bucket.
Use a Service Control Policy in AWS Organizations
An SCP can deny any attempt to disable Block Public Access, even by an account administrator.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyDisablingS3BlockPublicAccess",
"Effect": "Deny",
"Action": [
"s3:PutAccountPublicAccessBlock",
"s3:PutBucketPublicAccessBlock"
],
"Resource": "*",
"Condition": {
"Null": {
"s3:PublicAccessBlockConfiguration": "false"
}
}
}
]
}
Add a policy-as-code gate in CI/CD
Catch the problem before it reaches AWS. Tools like Checkov, tfsec, or OPA can fail a pull request when a bucket lacks Block Public Access. A Checkov scan is a one-liner in your pipeline:
checkov -d . --check CKV_AWS_53,CKV_AWS_54,CKV_AWS_55,CKV_AWS_56
Tip: Run Lensix continuously rather than only at deploy time. Block Public Access can be changed outside of your IaC pipeline, so ongoing detection catches drift that a one-time scan in CI would miss.
Best practices
- Isolate the log archive. Send CloudTrail logs to a dedicated logging account that almost nobody can touch. This limits blast radius if a workload account is compromised.
- Make logs immutable. Enable S3 Object Lock in compliance mode, or apply a bucket policy that denies
s3:DeleteObjectands3:PutObjectfor log objects, so an attacker cannot scrub history. - Enable log file validation. Turn on CloudTrail log file integrity validation so you can prove logs were not altered.
- Encrypt with a customer-managed KMS key. This adds a second access control layer and lets you audit who reads the logs.
- Scope the bucket policy tightly. Grant write access only to the
cloudtrail.amazonaws.comservice principal and read access only to the principals that genuinely need it. - Alert on access. Use S3 server access logging or a CloudWatch alarm on unusual
GetObjectactivity against the log bucket.
Locking down the CloudTrail bucket is low effort and high payoff. Block Public Access takes one API call, an SCP closes the loophole for good, and continuous monitoring keeps drift from creeping back in. Treat your audit trail as the crown jewels it is, and the rest of your incident response process gets a lot more reliable.

