AWS Security Hub · Cognito
Cognito.6: A Cognito user pool can be deleted by accident
Written and reviewed by Emnode · Last reviewed
What does AWS Security Hub Cognito.6 check?
Cognito.6 checks the DeletionProtection attribute on a user pool and fails when it is INACTIVE. With it ACTIVE, the delete-user-pool API is rejected until someone first calls update-user-pool to set it back to INACTIVE.
Why does Cognito.6 matter?
A user pool can be deleted in a single API call, and there is no soft-delete, recycle bin, or recovery path. The operation completes in seconds and takes every user record, password hash, MFA enrolment, group, app client, and identity-provider link with it. Every active session token becomes worthless and every logged-in customer is logged out mid-session. AWS Support cannot restore it: the only option is to rebuild and force a re-registration.
How do I fix Cognito.6?
- Set DeletionProtection to ACTIVE on every customer-facing user pool.
- Require the deliberate two-step (update to INACTIVE, then delete) for any genuine teardown.
- Pin the setting in IaC so stack re-applies do not silently turn it off.
Remediation script · bash
# Enable deletion protection on every unprotected standalone RDS instance in a region.
for id in $(aws rds describe-db-instances \
--query 'DBInstances[?DeletionProtection==`false`].DBInstanceIdentifier' --output text); do
aws rds modify-db-instance --db-instance-identifier "$id" \
--deletion-protection --apply-immediately
echo "Protected RDS instance: $id"
done
# Termination-protect every production-tagged CloudFormation stack (eyeball the list first).
aws cloudformation describe-stacks \
--query "Stacks[?Tags[?Key=='Environment' && Value=='production']].StackName" \
--output text | tr '\t' '\n' | while read -r stack; do
aws cloudformation update-termination-protection \
--stack-name "$stack" --enable-termination-protection
echo "Protected stack: $stack"
done
# Deletion-protect a production load balancer.
aws elbv2 modify-load-balancer-attributes --load-balancer-arn "$LB_ARN" \
--attributes Key=deletion_protection.enabled,Value=true Full walkthrough (console steps, edge cases and verification) in the lesson Enable deletion and termination protection.
Is Cognito.6 a false positive?
Short-lived user pools created for load tests, ephemeral preview environments, or per-PR integration stacks are meant to be torn down cleanly by the same automation that built them, so leaving DeletionProtection INACTIVE is the correct state. Turning it ACTIVE just makes the pool refuse the delete-user-pool call and strands the stack until someone manually runs update-user-pool. Confirm the pool holds no real customer identities and is owned by disposable infrastructure, then suppress the finding (or scope the control to production pools) rather than enabling protection on something designed to be destroyed.