AWS Security Hub · S3
S3.6: Bucket policy grants broad access to other AWS accounts
Written and reviewed by Emnode · Last reviewed
What does AWS Security Hub S3.6 check?
S3.6 inspects bucket policies for statements that grant another AWS account a set of sensitive administrative actions — including s3:DeleteBucketPolicy, s3:PutBucketAcl, s3:PutBucketPolicy, s3:PutEncryptionConfiguration and s3:PutObjectAcl. It reports FAILED when an external principal is allowed any of them.
Why does S3.6 matter?
These actions let another account rewrite the bucket's own access controls, not just read or write its data — handing over control of the bucket's security posture. A common cause is a well-meaning "Principal": "*" shortcut, which S3 reads as every AWS account on Earth plus anonymous callers, turning a private sharing bucket into one anyone can reconfigure.
How do I fix S3.6?
- Inventory every bucket policy and identify statements with an external or wildcard Principal.
- Confirm which cross-account integration each statement actually serves.
- Rewrite to a specific principal ARN and drop the administrative actions, keeping only the read/write the integration needs.
- Add an aws:SourceAccount or aws:SourceArn condition as a confused-deputy guard.
Remediation script · bash
# tightened-policy.json: external account keeps read-only, all admin actions removed,
# principal scoped to a role, and a confused-deputy guard added.
cat > tightened-policy.json <<'JSON'
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PartnerExportReadOnly",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::222233334444:role/acme-export-reader" },
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::acme-partner-exports/exports/*",
"Condition": { "StringEquals": { "aws:SourceAccount": "222233334444" } }
}
]
}
JSON
aws s3api put-bucket-policy --bucket acme-partner-exports --policy file://tightened-policy.json
# Verify no blacklisted action survives in the cross-account grant.
aws s3api get-bucket-policy --bucket acme-partner-exports --query Policy --output text \
| grep -E 's3:DeleteBucketPolicy|s3:PutBucketAcl|s3:PutBucketPolicy|s3:PutEncryptionConfiguration|s3:PutObjectAcl' \
&& echo 'STILL FAILING' || echo 'clean' Full walkthrough (console steps, edge cases and verification) in the lesson Lock down S3 bucket policies that hand sensitive actions to other AWS accounts.
More S3 controls
- S3.1 Account-level S3 public access is not fully blocked
- S3.2 Public S3 buckets expose data to anyone on the internet
- S3.3 Buckets can be written to by anyone on the internet
- S3.5 S3 is accepting unencrypted HTTP requests
- S3.8 Buckets can still be made public; Block Public Access is off
- S3.9 No S3 access logs, so reads and writes go unaudited
- S3.10 Versioned buckets should have lifecycle configurations
- S3.11 Buckets should have event notifications enabled
- S3.12 ACLs should not be used to manage bucket access
- S3.13 Buckets have no lifecycle rules and grow forever
- S3.15 Buckets should have Object Lock enabled
- S3.17 Buckets should be encrypted at rest with KMS keys