S3 BucketPolicy Self-Lockout
s3-bucket-policy-self-lockout
What this rule checks
Detects AWS::S3::BucketPolicy resources containing a Deny statement on s3:DeleteBucket, s3:*, or * with a broad Principal and no NotPrincipal or aws:PrincipalArn carveout for the account root or admin role. Such a policy locks the account out of its own bucket β recovery requires breaking glass on the account root credentials, since AWS Support typically declines to intervene where customers have a self-service path via root.
How to fix it
- 1Add a NotPrincipal exemption for the account root (arn:aws:iam::<account>:root) or admin role(s)
- 2Or use a Condition with StringNotEquals on aws:PrincipalArn to exempt admin role ARNs
- 3If the Deny is intended for transport security, scope it with aws:SecureTransport rather than a blanket Deny on Principal: '*'
import { aws_s3 as s3, aws_iam as iam } from 'aws-cdk-lib';
const bucket = new s3.Bucket(this, 'Bucket');
bucket.addToResourcePolicy(new iam.PolicyStatement({
sid: 'DenyAll',
effect: iam.Effect.DENY,
principals: [new iam.AnyPrincipal()],
actions: ['s3:DeleteBucket', 's3:PutBucketPolicy'],
resources: [bucket.bucketArn],
}));import { aws_s3 as s3, aws_iam as iam } from 'aws-cdk-lib';
const bucket = new s3.Bucket(this, 'Bucket');
bucket.addToResourcePolicy(new iam.PolicyStatement({
sid: 'DenyAll',
effect: iam.Effect.DENY,
notPrincipals: [new iam.AccountRootPrincipal()],
actions: ['s3:DeleteBucket', 's3:PutBucketPolicy'],
resources: [bucket.bucketArn],
}));CDK Insights pinpoints the exact file and line in your CDK source for every finding, so you can jump straight to the fix.
Affected resource types
AWS::S3::BucketPolicyIntentional? Suppress this finding
Sometimes a flag is deliberate β a genuinely public endpoint, say. You can dismiss s3-bucket-policy-self-lockout and the reason is kept in the report, not silently hidden.
In .cdk-insights.json:
{
"ignoreRules": [
{ "id": "s3-bucket-policy-self-lockout", "reason": "Why this is intentional" }
]
}Or inline in your CDK code:
Validations.of(scope).acknowledge({
id: 'cdk-insights::s3-bucket-policy-self-lockout',
reason: 'Why this is intentional',
});Use the rule ID s3-bucket-policy-self-lockout shown above β not the CDK-* ID from SARIF / GitHub code scanning. To dismiss every finding on one construct instead, use ignorePaths. Suppression docs β
Catch this in your stack
$ npx cdk-insights scanCDK Insights runs this and 118+ other rules locally against your synthesised CDK app β free, no account, your code never leaves your machine.