Skip to content

S3 buckets should have object lock enabled

Object Lock protects critical data from accidental or malicious deletion. Without it, any principal with s3:DeleteObject permissions can permanently remove objects, and even versioned buckets remain vulnerable to delete-marker floods or version-level purges. Ransomware operators routinely target backup buckets by deleting all object versions before demanding payment.

Enabling Object Lock at the bucket level establishes a baseline immutability guarantee. In governance mode, only users with s3:BypassGovernanceRetention can override retention. In compliance mode, nobody can delete protected objects, including the root account. This distinction matters when designing retention policies for regulated workloads.

Retrofit consideration

AWS now supports enabling Object Lock on existing buckets via the PutObjectLockConfiguration API, but the bucket must already have versioning enabled. The object_lock_enabled argument on aws_s3_bucket is a create-time-only setting in many provider versions, so Terraform may require an import workflow or a manual API call for pre-existing buckets. Test thoroughly in non-production before touching anything with live data.

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  = "soc2.compliance.tf/terraform-aws-modules/s3-bucket/aws"
  version = ">=5.0.0"

  bucket = "abc123"
}

module "s3_bucket" {
  source  = "pcidss.compliance.tf/terraform-aws-modules/s3-bucket/aws"
  version = ">=5.0.0"

  bucket = "abc123"
}

module "s3_bucket" {
  source  = "hipaa.compliance.tf/terraform-aws-modules/s3-bucket/aws"
  version = ">=5.0.0"

  bucket = "abc123"
}

module "s3_bucket" {
  source  = "nistcsf.compliance.tf/terraform-aws-modules/s3-bucket/aws"
  version = ">=5.0.0"

  bucket = "abc123"
}

module "s3_bucket" {
  source  = "fedrampmoderate.compliance.tf/terraform-aws-modules/s3-bucket/aws"
  version = ">=5.0.0"

  bucket = "abc123"
}

module "s3_bucket" {
  source  = "nist800171.compliance.tf/terraform-aws-modules/s3-bucket/aws"
  version = ">=5.0.0"

  bucket = "abc123"
}

module "s3_bucket" {
  source  = "nydfs23.compliance.tf/terraform-aws-modules/s3-bucket/aws"
  version = ">=5.0.0"

  bucket = "abc123"
}

module "s3_bucket" {
  source  = "ffiec.compliance.tf/terraform-aws-modules/s3-bucket/aws"
  version = ">=5.0.0"

  bucket = "abc123"
}

module "s3_bucket" {
  source  = "cfrpart11.compliance.tf/terraform-aws-modules/s3-bucket/aws"
  version = ">=5.0.0"

  bucket = "abc123"
}

module "s3_bucket" {
  source  = "rbiitfnbfc.compliance.tf/terraform-aws-modules/s3-bucket/aws"
  version = ">=5.0.0"

  bucket = "abc123"
}

module "s3_bucket" {
  source  = "hipaasecurity2003.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"
}

module "s3_bucket" {
  source  = "nist80053rev4.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"

  object_lock_enabled = true
}

Use AWS provider resources directly. See docs for the resources involved: aws_s3_bucket.

resource "aws_s3_bucket" "this" {
  bucket        = "pofix-abc123"
  force_destroy = true

  object_lock_enabled = true
}

What this control checks

This control checks that S3 buckets are created with Object Lock enabled. The aws_s3_bucket resource must have object_lock_enabled set to true. Because Object Lock requires versioning, the bucket must also have versioning enabled via a separate aws_s3_bucket_versioning resource with versioning_configuration status set to "Enabled". A default retention policy can then be configured using aws_s3_bucket_object_lock_configuration, specifying rule.default_retention with a mode of "GOVERNANCE" or "COMPLIANCE" and a days or years value.

The control passes when object_lock_enabled is true. It fails when the argument is absent, set to false, or the bucket was created without Object Lock support.

Common pitfalls

  • Object Lock is immutable at creation in older provider versions

    In many Terraform AWS provider versions, object_lock_enabled on aws_s3_bucket is a ForceNew argument. Changing it from false to true destroys and recreates the bucket, which deletes all existing objects. Always check provider release notes before planning this change, and consider using aws s3api put-object-lock-configuration for existing buckets before importing state.

  • Versioning must be enabled first

    The API call fails if versioning isn't already enabled when Object Lock is configured. Create the aws_s3_bucket_versioning resource with status "Enabled" before or alongside object_lock_enabled = true, and add an explicit depends_on if Terraform's implicit dependency ordering isn't guaranteed. The plan won't always warn you when this is missing.

  • Compliance mode retention cannot be shortened

    Setting mode to "COMPLIANCE" in aws_s3_bucket_object_lock_configuration means no one, including the root user, can delete protected objects or shorten the retention period before it expires. Get this wrong with a long retention window and you're waiting it out. Use "GOVERNANCE" mode during testing and only promote to "COMPLIANCE" once the period is validated.

  • Object Lock does not retroactively protect existing objects

    Enabling Object Lock and configuring a default retention policy only applies to objects uploaded after the policy is in place. Existing objects in the bucket are not automatically protected. Apply retention settings per-object using aws s3api put-object-retention, or re-upload objects so they inherit the default.

  • Lifecycle rules interact with retention

    S3 lifecycle expiration rules cannot delete objects still under Object Lock retention. The lifecycle action silently fails for locked objects, which can produce unexpected storage costs if you assumed lifecycle would prune old data. Audit lifecycle rule interactions before setting long retention periods.

Audit evidence

Auditors expect AWS Config evaluation results showing compliant status across all in-scope buckets. Console evidence should show Object Lock as "Enabled" under the bucket's Properties tab, along with the configured default retention mode and period. CloudTrail logs for PutObjectLockConfiguration and CreateBucket provide a timeline of when Object Lock was enabled and by whom.

For continuous assurance, Security Hub evaluations or a third-party CSPM showing periodic scan results with passing evaluations rounds out the evidence package.

Framework-specific interpretation

SOC 2: Availability and Processing Integrity both ask whether unauthorized deletion or alteration of retained data is technically prevented. For S3 storage, Object Lock gives you a direct technical control that addresses both criteria.

PCI DSS v4.0: Requirement 3 covers protection of stored account data; Requirement 10 covers log integrity. For cardholder data or audit logs living in S3, Object Lock helps preserve that data against unauthorized deletion, which is what examiners look for under both requirements.

HIPAA Omnibus Rule 2013: 45 CFR 164.312(c)(1) requires integrity controls that guard ePHI against improper alteration or destruction. Object Lock in compliance mode helps ensure that ePHI stored in S3 cannot be removed or overwritten during the required retention window, addressing the technical safeguard specification directly.

NIST Cybersecurity Framework v2.0: PR.DS covers data protection at rest; RC.RP covers recovery planning and data availability. Object Lock contributes to both: it closes the credential-compromise path to wiping stored data, and it gives recovery procedures something reliable to work from when restoring from S3-backed backups.

FedRAMP Moderate Baseline Rev 4: SI-12 and CP-9 cover information retention and backup protection at the Moderate baseline. Object Lock provides one mechanism for the tamper-resistant storage both controls expect, particularly for backup and archival data where integrity must be demonstrable to assessors.

Tool mappings

Use these identifiers to cross-reference this control across tools, reports, and evidence.

  • Compliance.tf Control: s3_bucket_object_lock_enabled

  • AWS Config Managed Rule: S3_BUCKET_DEFAULT_LOCK_ENABLED

  • Checkov Check: CKV_AWS_143

  • Powerpipe Control: aws_compliance.control.s3_bucket_object_lock_enabled

  • Prowler Check: s3_bucket_object_lock

  • AWS Security Hub Control: S3.15

Last reviewed: 2026-03-09