Amazon S3 SSE-C Default Disable (April 2026): Migration Playbook
Quick summary: After the April 2026 S3 default that blocks SSE-C on new buckets (and on existing buckets in accounts with zero SSE-C objects), a SaaS media platform (~2.4 PB, 418 buckets) found 11 legacy upload paths still sending customer-key headers — all failing 403 until migrated to SSE-KMS.
Key Takeaways
- After the April 2026 S3 default that blocks SSE-C on new buckets (and on existing buckets in accounts with zero SSE-C objects), a SaaS media platform (~2
- 4 PB, 418 buckets) found 11 legacy upload paths still sending customer-key headers — all failing 403 until migrated to SSE-KMS
- New SSE-C uploads then fail with HTTP 403 AccessDenied unless you explicitly re-allow SSE-C via (What's New, FAQ, blocking guide)
- First-party benchmark silhouette — SaaS media platform, ~2
- 4 PB, 418 buckets, multi-account

Table of Contents
In April 2026, Amazon S3 rolled out a default bucket security setting that disables SSE-C (server-side encryption with customer-provided keys) for all new general purpose buckets, and for existing buckets in accounts that had no SSE-C encrypted objects. New SSE-C uploads then fail with HTTP 403 AccessDenied unless you explicitly re-allow SSE-C via PutBucketEncryption (What’s New, FAQ, blocking guide).
This is the migration / audit playbook. It is not a remake of KMS CMK architecture.
Artifacts: audit checklist, CLI probe script, architecture diagram (draw.io).
First-party benchmark silhouette — SaaS media platform, ~2.4 PB, 418 buckets, multi-account. Inventory + CloudTrail scan after the April rollout found 11 upload paths (mobile SDK + 2 ETL jobs) still attaching SSE-C headers. Those paths began returning 403 on buckets that received the default block. Cutover to SSE-KMS CMKs cleared errors in 4 engineer-days; remaining SSE-C objects kept readable-with-key until a cold archive rewrite.
What changed (operator view)
| Account state before April 2026 | Existing buckets | New buckets |
|---|---|---|
| No SSE-C objects anywhere | SSE-C writes blocked | SSE-C blocked by default |
| Any SSE-C object in the account | Config unchanged | SSE-C blocked by default |
When blocked, SSE-C on PutObject / CopyObject / PostObject / multipart / replication → 403. GetObject / HeadObject of existing SSE-C objects still require customer-key headers.

Figure: writers migrate from customer-provided keys to SSE-KMS; bucket encryption shows BlockedEncryptionTypes SSE-C; legacy objects remain readable with old keys until rewritten. Open draw.io
Opinionated recommendation
Do not re-enable SSE-C for net-new apps. Prefer SSE-KMS when you need key policy, audit, and cross-account grants; SSE-S3 when default protection is enough. Use SSE-C only as a dated exception with an owner and kill date.
SSE-C forces every reader/writer to possess the raw key — hostile to IAM roles, Lake Formation grants, and most AWS analytics services.
Audit sequence
- Account question — Did we ever store SSE-C objects? Inventory encryption columns + CloudTrail
x-amz-server-side-encryption-customer-algorithm. - Writer hunt — Grep for
SSECustomerKey, customer algorithm headers, third-party “client-side key” wrappers that still speak SSE-C to S3. - Bucket sample —
get-bucket-encryption; look forBlockedEncryptionTypes→SSE-C. - Probe — intentional SSE-C
PutObjectshould 403 when blocked (staging buckets only).
# Spot-check encryption config (AWS CLI v2)
aws s3api get-bucket-encryption \
--bucket amzn-s3-demo-bucket \
--region us-east-1Reproduce this — Run audit-ssec-inventory.sh per critical bucket, then work the sse-c-audit-checklist.md with security + platform owners.
What broke — Day after rollout. A partner integrator still used SSE-C on a new logging bucket. Uploads returned 403 AccessDenied; on-call assumed IAM regression. Root cause: default
BlockedEncryptionTypes. Fix: switched integrator to SSE-KMS; did not clear the block. Lesson: treat 403 + SSE-C headers as the new default, not an IAM mystery.
Explicit allow (exception path)
If you truly need SSE-C on a new bucket: create the bucket, then call PutBucketEncryption clearing the block (BlockedEncryptionTypes → NONE per FAQ examples). Requires s3:PutEncryptionConfiguration. Document the exception and remove it when the writer migrates.
What to Do This Week
- Complete the account-level “any SSE-C objects?” scan.
- Ticket every upload path that still sets customer-key headers.
- Migrate those writers to SSE-KMS (or SSE-S3) in staging first.
- Confirm
BlockedEncryptionTypesincludes SSE-C on high-risk buckets. - Add a CI check that fails if new code introduces SSE-C headers.
What This Post Doesn’t Cover
- Client-side encryption SDKs that never used SSE-C headers (different model)
- Full CMK rotation / key policy design — KMS architecture
- Macie classification of historical SSE-C objects — Macie + Detective
- Directory buckets / S3 Express nuances — verify current docs for those API surfaces
We have not re-tested Middle East (Bahrain/UAE) exceptions after April 2026 — re-read the FAQ before assuming region behavior.
Related: Cloud security · Compliance services · KMS cost traps
AWS Cloud Architect & AI Expert
AWS-certified cloud architect and AI expert with deep expertise in cloud migrations, cost optimization, and generative AI on AWS.




