Scope
This guide focuses on detecting, fixing, and continuously monitoring over-permissioned Amazon S3 buckets in both single- and multi-account AWS setups. You'll find steps for automated scanning, policy remediation workflows, and ongoing compliance checks using AWS Config, Lambda, and Security Hub.
Key Concepts and Definitions
Over-permissioned bucket: An S3 bucket with any of these issues:
- Public Access Block settings are disabled
- Bucket policy allows public read or write access
- ACL grants to
AllUsersorAuthenticatedUsers
Public Access Block: Four S3 settings that block public access regardless of bucket policies or ACLs:
BlockPublicAclsIgnorePublicAclsBlockPublicPolicyRestrictPublicBuckets
Cross-account audit role: An IAM role in member accounts that your central security account assumes to scan S3 configurations. It must include an external ID condition to prevent the confused deputy problem.
Confused deputy problem: A security risk where an attacker manipulates a more privileged service to perform actions on their behalf. Prevent this by requiring an external ID in your cross-account trust policy.
Requirements Breakdown
Your audit function must check three configuration areas for each bucket:
1. Public Access Block status
- Ensure all four settings are enabled
- Flag any bucket with one or more disabled settings
2. Bucket policy evaluation
- Look for
Principal: "*"orPrincipal: {"AWS": "*"} - Check for
Effect: "Allow"with a public principal - Identify policies allowing
s3:GetObjectors3:PutObjectwithout IP or VPC restrictions
3. ACL grant inspection
- List ACL grants for each bucket
- Flag grants to
http://acs.amazonaws.com/groups/global/AllUsers - Flag grants to
http://acs.amazonaws.com/groups/global/AuthenticatedUsers
Implementation Guidance
Phase 1: Environment Setup
Set up AWS Organizations or cross-account IAM roles before deploying audit tools. Designate one account as your central security account.
Create the SNS topic for alerts first. You'll need its ARN when setting up the Lambda execution role and function code. Confirm email subscriptions immediately; SNS won't deliver alerts until you click the confirmation link.
For the Lambda execution role, grant only:
- S3 read permissions (
s3:ListAllMyBuckets,s3:GetBucketPolicy,s3:GetBucketAcl,s3:GetPublicAccessBlock) - SNS publish to your specific topic ARN
- CloudWatch Logs write permissions
sts:AssumeRolefor cross-account scanning (if applicable)
Phase 2: Deploy AWS Config Rules
Enable AWS Config in all member accounts. Deploy these managed rules:
s3-bucket-public-read-prohibiteds3-bucket-public-write-prohibited
These rules provide real-time detection between your scheduled Lambda scans. Findings flow automatically to Security Hub when you configure it as the central administrator.
Phase 3: Lambda Function Deployment
You have two script options:
Script v1 scans buckets and sends immediate SNS alerts. Use this for real-time notifications when your security team needs to respond quickly.
Script v2 generates CSV and JSON reports uploaded to an S3 bucket. Use this for historical analysis, trend reporting, or integration with business intelligence tools.
Deploy both if you need immediate alerts and historical records.
Phase 4: Automated Remediation
Build a separate remediation Lambda function triggered by your audit findings. This function should:
- Apply a deny-public-access bucket policy
- Enable all four Public Access Block settings
- Remove ACL grants to
AllUsersandAuthenticatedUsers - Log all changes to CloudTrail
For multi-account environments, use CloudFormation StackSets to deploy standardized bucket policies across accounts. This ensures consistency and reduces drift.
Phase 5: Continuous Monitoring
Schedule your audit Lambda using EventBridge rules. Run daily scans in production environments, weekly in development.
Configure EventBridge to detect S3 policy changes in real time:
{
"source": ["aws.s3"],
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"eventName": ["PutBucketPolicy", "PutBucketAcl", "DeletePublicAccessBlock"]
}
}
Enable IAM Access Analyzer for S3 to identify external access patterns your policy scans might miss. Access Analyzer uses automated reasoning to determine what resources are accessible outside your account. IAM Access Analyzer
Common Pitfalls
Incomplete Public Access Block coverage: You enable Public Access Block at the account level but forget to enable it at the bucket level. Both must be configured. Account-level settings don't override existing bucket-level configurations.
Missing external ID in trust policies: Your cross-account roles lack external ID conditions, creating confused deputy vulnerabilities. Always require an external ID that only your security account knows.
SNS subscription not confirmed: You deploy the Lambda function but never confirm the email subscription. The function runs successfully but you receive no alerts. Check your email and confirm subscriptions before testing.
Overly broad remediation: Your automated remediation function enables Public Access Block on every bucket, breaking legitimate public hosting use cases. Maintain an exception list for buckets that require public access (static website hosting, public datasets).
Ignoring ACL grants to authenticated users: Your audit checks for AllUsers but not AuthenticatedUsers. The latter grants access to any AWS account holder worldwide. Flag both.
Lambda timeout on large environments: Your function times out when scanning hundreds of buckets. Implement pagination and consider splitting scans across multiple invocations using Step Functions.
Quick Reference Table
| Check | Configuration Item | Compliant State | Risk if Non-Compliant |
|---|---|---|---|
| Public Access Block | BlockPublicAcls |
true |
New ACLs can grant public access |
| Public Access Block | IgnorePublicAcls |
true |
Existing public ACLs remain active |
| Public Access Block | BlockPublicPolicy |
true |
New policies can allow public access |
| Public Access Block | RestrictPublicBuckets |
true |
Existing public policies remain active |
| Bucket Policy | Principal element |
No "*" or {"AWS": "*"} |
Unrestricted public access |
| Bucket ACL | Grantee | No AllUsers or AuthenticatedUsers |
Bucket contents readable by anyone |
| AWS Config Rule | s3-bucket-public-read-prohibited |
COMPLIANT |
Public read access undetected |
| AWS Config Rule | s3-bucket-public-write-prohibited |
COMPLIANT |
Public write access undetected |
Cost drivers: AWS Config charges per configuration item recorded and per rule evaluation. Security Hub charges per account per region. Start with a pilot in one or two accounts to validate costs before scaling to your full environment.



