Skip to main content

S3 Default Bucket Encryption Skips Every Object Uploaded Before It Was Enabled

Medium severityAmazon Web Services About 20 minutes to fixGenerated 14 Aug 2026

Overview

Turning on Amazon S3 default bucket encryption looks like a bucket-wide fix, but it only governs new writes. Objects already stored before the change remains untouched, and audits that trust the flag alone miss it.

At a glance

Symptom
Enabling S3 Bucket Default Encryption on an existing bucket does not encrypt the objects that were already stored there before the setting was applied…
Likely cause
The root cause is that S3 bucket-level default encryption is a write-time policy, not a retroactive transformation: it determines what encryption AWS applies to…
Impact
The operational consequence is a false sense of assurance: a security review that checks only the bucket's default-encryption configuration will report the bucket as encrypted, while any object…
Verification signal
Validation confirms that every previously unencrypted object now reports the intended encryption algorithm on inspection, not merely that the bucket-level default remains enabled.Re-run aws s3api head-object against every…
Safe correction
The correction is to explicitly rewrite each identified unencrypted object using a copy-in-place operation that applies the desired encryption setting, because the bucket-level default only governs future writes…
Rollback or recovery
Rollback is only viable when S3 Versioning was confirmed enabled before the correction ran, because a copy-in-place under versioning creates a new object version rather than mutating the…

Symptom

Enabling S3 Bucket Default Encryption on an existing bucket does not encrypt the objects that were already stored there before the setting was applied, so a subset of stored data remains in its original, unencrypted state even though every bucket-level dashboard reports the encryption control as “Enabled”.

A typical trigger is a migrated logging or archive bucket: a platform team turns on server-side encryption (SSE-S3 or SSE-KMS) as part of a security remediation sprint, closes the associated ticket, and later discovers during an access-control or breach-readiness review that a meaningful share of the objects in that bucket still return no ServerSideEncryption header when inspected individually.

False Assumption

The team assumed that switching on default encryption is a bucket-wide, backward-applying control: that flipping the toggle brings every object currently stored in the bucket into an encrypted state, not only the objects written after the setting was applied.

That assumption is reinforced by the console language itself. The setting is presented as a property of the bucket (“Default encryption: Enabled”) rather than as a rule that only governs future PutObject calls. Change-management sign-off in this scenario reviewed the configuration flag as evidence of completion, because verifying encryption status for every object in a large bucket individually is neither the default audit method nor something most teams build into a standard change review.

Root Cause

The root cause is that S3 bucket-level default encryption is a write-time policy, not a retroactive transformation: it determines what encryption AWS applies to an object at the moment it is written, and it has no effect on objects that already exist in the bucket at the time the setting is changed.

The AWS S3 documentation on default encryption states that the setting applies to new object uploads and does not re-encrypt existing objects. AWS also applies SSE-S3 to new uploads by default (rolled out from January 2023), so the gap mainly affects objects written before that default applied. Check the current AWS documentation for exact behaviour in your account.

Impact

The operational consequence is a false sense of assurance: a security review that checks only the bucket’s default-encryption configuration will report the bucket as encrypted, while any object written before that setting was enabled remains exactly as it was, unprotected by the control the review believes is in effect.

For regulated workloads, this gap can invalidate an encryption-at-rest attestation for a specific date range, complicate breach-notification scoping if the bucket is later implicated in an incident, and propagate a false assurance into downstream audits or customer-facing security statements that cite the bucket-level flag as evidence.

Diagnosis

Diagnosis starts by separating the bucket-level configuration from the per-object reality, using read-only checks before any object is touched.

  1. Confirm the current default-encryption configuration with aws s3api get-bucket-encryption.
  2. Confirm whether S3 Versioning is enabled with aws s3api get-bucket-versioning; this determines whether any later correction can be rolled back.
  3. Take a bounded sample of object keys with aws s3api list-objects-v2, prioritising objects known or suspected to predate the default-encryption change.
  4. Inspect each sampled key individually with aws s3api head-object and check for the presence of the ServerSideEncryption field.
aws s3api get-bucket-encryption --bucket example-logging-bucket
aws s3api get-bucket-versioning --bucket example-logging-bucket
aws s3api list-objects-v2 --bucket example-logging-bucket --max-items 50 --query 'Contents[].Key'
aws s3api head-object --bucket example-logging-bucket --key logs/2024/01/01/access.log

An object with no ServerSideEncryption field in its head-object output was most likely written before default encryption applied and is unencrypted; it requires the correction below, because changing the bucket setting does not retroactively encrypt it.

Correction

The correction is to explicitly rewrite each identified unencrypted object using a copy-in-place operation that applies the desired encryption setting, because the bucket-level default only governs future writes and cannot be relied upon to change existing objects.

Required preconditions, in order: first, verify that S3 Versioning is enabled (or that a separate backup copy of the objects exists). Without one of these, the rewrite overwrites the original irreversibly. Versioning increases storage costs and should be enabled by the bucket owner under change control. Second, record the existing metadata, tags and ACLs of each object (for example with aws s3api head-object, get-object-tagging and get-object-acl). Third, test on a single object. Only then proceed.

aws s3 cp s3://example-logging-bucket/logs/2024/01/01/access.log s3://example-logging-bucket/logs/2024/01/01/access.log --sse AES256 --metadata-directive REPLACE

With --metadata-directive REPLACE, metadata is not carried over, so re-supply any recorded metadata (content type and so on) explicitly in the command. Alternatively use aws s3api copy-object with explicit settings. Tags and ACLs are not preserved by default and may need to be reapplied, and objects larger than 5 GB need a multipart copy, which the high-level aws s3 cp command handles but should be tested first.

Before any bulk run, work only from an approved list of keys and cap the batch size. For buckets holding more than a few hundred affected objects, a per-object CLI loop does not scale reliably against request-rate and execution-time limits; scope the work instead to a manifest-driven batch job covering only the keys confirmed unencrypted in the diagnosis step, and re-verify a sample afterwards rather than assuming the job succeeded uniformly.

Validation

Validation confirms that every previously unencrypted object now reports the intended encryption algorithm on inspection, not merely that the bucket-level default remains enabled.

  • Re-run aws s3api head-object against every corrected key and confirm the ServerSideEncryption field now matches the intended algorithm, and that metadata and tags match what you recorded.
  • Re-run aws s3api get-bucket-encryption to confirm the bucket-level configuration is unchanged by the correction itself.
  • If S3 Inventory or an equivalent reporting mechanism is configured, confirm the corrected keys no longer appear in an unencrypted-object report.

Rollback

Rollback is only viable when S3 Versioning was confirmed enabled (or a backup copy exists) before the correction ran, because a copy-in-place under versioning creates a new object version rather than mutating the object irreversibly.

  1. Identify the prior version ID with aws s3api list-object-versions --bucket example-logging-bucket --prefix logs/2024/01/01/access.log.
  2. Restore the prior content if the correction caused an unexpected application or integrity failure, for example with aws s3api copy-object --bucket example-logging-bucket --key logs/2024/01/01/access.log --copy-source 'example-logging-bucket/logs/2024/01/01/access.log?versionId=VERSION_ID' --metadata-directive REPLACE --server-side-encryption AES256, URL-encoding the key in the copy source if it contains special characters. A same-key copy must change an attribute such as metadata or encryption, otherwise S3 rejects it. This creates a new version rather than removing the corrected one. Restored content cannot realistically return to an unencrypted state, since bucket default encryption will encrypt it anyway; verify metadata, tags and encryption afterwards. Alternatively, if the correction produced the latest version, deleting that version by its version ID makes the prior version current again.
  3. If versioning was not enabled and no backup exists, treat the prior object content as unrecoverable, record this as a permanent limitation in the change record, and escalate to the data owner rather than attempting an unsupported restore.

Prevention

Preventing recurrence means treating the default-encryption toggle as a forward-only control in every future change-management review, rather than as proof that existing data is protected.

  • Enable default encryption at bucket creation time wherever possible, so there is no window in which unencrypted objects can be written.
  • Consider a bucket policy condition that denies s3:PutObject requests lacking the expected x-amz-server-side-encryption header. Be aware that this will break uploaders that rely on the default encryption and do not send the header, so test it first and roll it out in stages, with a way to remove the policy if clients fail.
  • Enable S3 Versioning before enabling default encryption on any bucket that may later need object-level correction, so remediation work remains reversible.
  • Use S3 Inventory, or an equivalent scheduled report, to track per-object encryption status as an ongoing signal, and treat the bucket-level configuration flag as only one input into a compliance attestation, never the sole evidence.

3

Apply the safer control

Before you change production

Confirm the affected scope, export the current configuration, and test the replacement control in a non-production environment first.

Fix commands and configuration

ServerSideEncryption
PutObject
aws s3api get-bucket-encryption
4

Verify, roll back or escalate

Verify

Validation confirms that every previously unencrypted object now reports the intended encryption algorithm on inspection, not merely that the bucket-level default remains enabled.Re-run aws s3api head-object against every corrected key and confirm the ServerSideEncryption field now matches the intended algorithm.Re-run…

Rollback

Rollback is only viable when S3 Versioning was confirmed enabled before the correction ran, because a copy-in-place under versioning creates a new object version rather than mutating the object irreversibly.Identify the prior version ID with aws s3api list-object-versions --bucket example-logging-bucket…

Escalate

Escalate when the blast radius is uncertain, the control cannot be tested safely, or remediation requires an outage or security exception.

The KBY Brief

Fixed? Get the next one before it hits you: The KBY Brief

Practical fixes for the systems you run, by email about twice a week. Unsubscribe at any time.

About this page

Credited to

Dates

Published

Last updated

Corrections

  • : Corrected during a review of published articles. Details

Was this useful?

Reports go to the site owner and are used to correct pages. Corrections are listed at /corrections.

After remediation

Further reading stays below the corrective workflow and is selected by platform, category and shared technical keywords.

Discover more

Connected KBY resources