S3 buckets should have MFA delete enabled
Without MFA Delete, anyone with sufficient IAM permissions can permanently remove object versions or suspend versioning. A compromised credential or overly permissive policy can cause irreversible data loss with no recovery path. MFA Delete adds a second authentication factor that blocks automated or unauthorized deletion attempts, including those from valid but compromised credentials.
This matters most for buckets storing backups, audit logs, or regulated data where tamper-proof retention is required. Ransomware commonly targets versioning and delete operations to eliminate recovery options, and MFA Delete is one of the few controls that actually stops that pattern.
Retrofit consideration
MFA Delete can only be enabled by the root account using the AWS CLI with an MFA token. Terraform cannot enable it autonomously because the API call requires live MFA credentials. Retrofitting existing buckets requires a manual, root-level operation per bucket.
Implementation
Choose the approach that matches how you manage Terraform.
Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.
module "s3_bucket" {
source = "pcidss.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "cis.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "cisv500.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "acscessentialeight.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "cisv120.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
module "s3_bucket" {
source = "nistcsfv11.compliance.tf/terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
}
If you use terraform-aws-modules/s3-bucket/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.
module "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = ">=5.0.0"
bucket = "abc123"
versioning = {
mfa_delete = "Enabled"
}
}
Use AWS provider resources directly. See docs for the resources involved: aws_s3_bucket_versioning.
resource "aws_s3_bucket" "this" {
bucket = "pofix-abc123"
force_destroy = true
}
resource "aws_s3_bucket_versioning" "this" {
bucket = "example-bucket-abc123"
versioning_configuration {
mfa_delete = "Enabled"
status = "Enabled"
}
}
What this control checks
This control validates that both versioning and MFA Delete are enabled on the bucket. It fails when versioning is suspended or absent, or when MFA Delete is not enabled.
In AWS, enabling or disabling MFA Delete requires a PutBucketVersioning request authenticated as the root account and including a valid MFA code. Because of this root-plus-MFA requirement, many teams configure MFA Delete out-of-band using aws s3api put-bucket-versioning and treat it as an externally managed setting in Terraform.
Common pitfalls
Root account required for enablement
The
PutBucketVersioningAPI call with MFA Delete requires root account credentials and a valid MFA token. IAM users and roles cannot enable MFA Delete regardless of their permissions. Terraform runs using IAM roles will fail to apply this setting, producing anAccessDeniederror.Terraform cannot fully manage MFA Delete lifecycle
Terraform cannot manage MFA Delete through normal provider workflows. Changing MFA Delete requires a root-authenticated request with a current MFA code, which automated pipelines cannot produce. Enable it via
aws s3api put-bucket-versioningin the CLI, then exclude that setting from Terraform state management entirely.Disabling MFA Delete also requires MFA
Once enabled, MFA Delete cannot be disabled without root account access and a valid MFA token. If root MFA access is lost, you cannot revert this setting. Document and test root MFA recovery procedures before enabling.
Versioning must also be enabled
MFA Delete only applies when versioning is active. If
versioning_configuration.statusis set to"Suspended"or omitted, MFA Delete has no practical effect even if the flag appears in the API response.
Audit evidence
An auditor expects to see the output of aws s3api get-bucket-versioning --bucket <bucket-name> showing both "Status": "Enabled" and "MFADelete": "Enabled" for each in-scope bucket. AWS Config rules such as s3-bucket-versioning-enabled provide continuous compliance evaluation results, though a custom Config rule or third-party scanner specifically flagging MFA Delete status is stronger evidence.
CloudTrail logs for PutBucketVersioning events should confirm MFA Delete was configured, with the x-amz-mfa header present in the request. Tools like Prowler or Steampipe that enumerate MFA Delete status across all buckets work as periodic attestation artifacts.
Framework-specific interpretation
PCI DSS v4.0: Requirement 8.4 calls for MFA on all access into the cardholder data environment. For buckets storing cardholder data, MFA Delete means that even a fully authenticated principal with broad S3 permissions cannot permanently destroy object versions without a second factor, which is the exact assurance Requirement 8 is after.
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
s3_bucket_mfa_delete_enabledAWS Config Managed Rule:
S3_BUCKET_MFA_DELETE_ENABLEDPowerpipe Control:
aws_compliance.control.s3_bucket_mfa_delete_enabledProwler Checks:
cloudtrail_bucket_requires_mfa_delete,s3_bucket_no_mfa_deleteAWS Security Hub Control:
S3.20KICS Query:
c5b31ab9-0f26-4a49-b8aa-4cc064392f4dTrivy Check:
AWS-0170
Last reviewed: 2026-03-09