✓ Human-authored analysis; AI used for formatting and proofreading.
Your compliance dashboard says 100% of S3 buckets are encrypted. Your audit report says every RDS database uses KMS encryption. Your security scanner reports zero encryption findings.
All 23 resources are encrypted with the same key.
Nobody checked.
How It Happens
Nobody plans a common mode failure. It accumulates.
Day 1: a team creates a KMS key for a new project. They encrypt the first S3 bucket. Correct, responsible, compliant.
Day 30: a new bucket is needed for the same project. "Use the same key — it's already set up, the key policy already grants access, one less thing to configure." Reasonable.
Day 90: an RDS database is added. "Use the same key — one key policy to manage instead of two." Faster.
Day 180: EBS volumes for new EC2 instances. "Same key." Nobody questions it. The team has shipped three features this quarter. Key management is not on the roadmap.
Day 365: 23 resources depend on one KMS key. 12 S3 buckets. 6 RDS databases. 3 EBS volumes. 2 Secrets Manager secrets. Nobody planned this. Each decision was individually reasonable. The total is a single point of failure that nobody has measured.
Day 400: a Terraform update replaces the key policy. The developer included the application roles but forgot to include kms:PutKeyPolicy for the admin role. The key is now orphaned. It exists, nobody can modify its policy, and the application roles that were in the old policy are gone. None of the 23 resources can decrypt their data. The S3 buckets return AccessDenied on every GetObject call. The RDS databases transition to inaccessible-encryption-credentials and stop. The EBS volumes won't mount. The secrets can't be read.
Twenty-three resources down. One root cause. One key.
Why Every Tool Misses It
Every security tool evaluates resources individually.
"Is this S3 bucket encrypted?" Yes. ✅
"Is this RDS database encrypted?" Yes. ✅
"Is this EBS volume encrypted?" Yes. ✅
Twenty-three checks. Twenty-three passes. Zero findings. The audit is green. The compliance report looks good. The risk is invisible. Because the risk isn't in any individual resource. The risk is in the relationship between resources. The risk is in the graph, not the node.
No tool asks:
- "How many resources share this KMS key?"
- "What is the blast radius if this key becomes unavailable?"
- "Is this key a single point of failure?"
The individual configuration is correct. The shared dependency is the risk. The shared dependency is invisible to every per-resource scanner on the market.
The Failure Modes
A shared KMS key creates three distinct failure modes, each with a different trigger and a different blast radius.
Failure mode 1: Availability — key disruption.
The key is disabled, scheduled for deletion, or its key policy is modified to remove access for the roles that need it. Every resource encrypted with that key loses the ability to read or write data. The blast radius is every resource that references the key's ARN.
IAM policy cleanups routinely tighten permissions without checking which KMS key policies reference the modified roles. A departing employee's access is revoked, and the automation that revokes it doesn't know that the employee's role was the only principal with kms:Decrypt in the key policy for the production encryption key. The key still exists. Nobody can use it.
Failure mode 2: Confidentiality — key compromise.
An attacker who obtains kms:Decrypt permission for one key gains access to the data in every resource encrypted with that key. If 12 S3 buckets share one key, compromising access to that key exposes all 12 buckets — not just the one the attacker targeted.
The Capital One breach demonstrated this pattern at scale. The compromised role had access to S3 objects encrypted with keys it could decrypt. The blast radius wasn't one bucket. It was every bucket the key policy permitted — over 700.
Failure mode 3: Compliance — blast radius exceeds certification scope.
A compliance framework certifies that specific resources meet specific controls. If a key shared across 23 resources is involved in a compliance incident, the blast radius of the investigation expands to all 23 resources. Even if only one was in scope for the original certification. The compliance team must now determine whether 22 additional resources were affected, re-certify the scope, and explain to the auditor why a single key was shared across certified and uncertified resources.
Failure mode 4: Throttling — unrelated services die together.
AWS KMS has request quotas — typically 10,000 to 50,000 cryptographic operations per second depending on the region and key type. If 23 resources share one key, they share the same quota. A traffic spike in Service A (S3 bulk uploads encrypting thousands of objects per second) consumes the quota that Service B (RDS) needs to sustain database connections. RDS returns ThrottlingException on its decrypt calls. The database can't perform cryptographic operations. Connections fail. The database goes down, because an unrelated S3 bulk upload consumed the shared key's quota.
The services have no architectural relationship. They don't communicate. They don't share a VPC or a security group. They share a KMS key. That shared key couples their availability through an invisible throttling ceiling that no monitoring dashboard shows. Because the throttling is attributed to the KMS API, not to the relationship between the services.
The KMS Grants dimension amplifies all four failure modes.
In large-scale AWS environments, services like EBS and RDS don't use the key policy directly. They use KMS Grants, temporary permissions the service creates when attaching an encrypted volume or starting an encrypted database. An automated cleanup script looking for "stale grants" might retire grants for 23 active resources at once. A single RevokeGrant or RetireGrant call removes access for the specific service-to-key relationship. If 23 services depend on grants to the same key, a cleanup script that doesn't understand the dependency graph can revoke all 23 grants in one batch. The same common mode failure triggered by automation that was supposed to improve security posture.
The Cost Counter-Argument
Why do teams share keys?
Each AWS KMS Customer Managed Key costs $1.00 per month. For a startup with 23 resources, the choice is $1/month (one shared key) versus $4/month (one key per service) versus $23/month (one key per resource). The cost difference is trivial.
But for an organization with 500 microservices, the choice is $1/month versus $500/month. At scale, the cost becomes a line item that a manager questions: "Why are we paying $500/month for encryption keys when $1 works?"
The answer: "Is $499/month worth the insurance against a total infrastructure blackout?" One shared key means one incident takes everything down. Five hundred dedicated keys means one incident takes down one service. The $499 buys blast radius isolation. The same isolation that the organization spends millions on for network segmentation, account separation, and availability zones. But nobody applies that thinking to encryption keys because nobody measures the blast radius of a shared key.
The Pattern is Not Limited to KMS
KMS is the most visible example because encryption is universally mandated. But the common mode failure pattern appears wherever resources share a dependency that can fail independently of the resources themselves.
Shared IAM execution role: five Lambda functions use the same execution role. The role's permissions are tightened. All five functions fail simultaneously. The developer who tightened the permissions was fixing a finding on one function and didn't know four others shared the role.
Shared VPC: every production service runs in one VPC. A route table misconfiguration, a CIDR conflict from a VPC peering connection, or a NACL rule change affects every service in the VPC simultaneously. The blast radius is the entire production environment.
Shared security group: eight EC2 instances reference the same security group. A rule change intended for one instance affects all eight. The developer modified the security group for "the web server" without knowing that "the database server" and six other instances share it.
Shared S3 bucket for logs: every service writes logs to one bucket. The bucket policy is modified. Every service loses logging simultaneously. The CloudTrail trail that would have recorded what went wrong is also writing to the same bucket. The audit trail is gone.
In every case, the individual resource is correctly configured. The shared dependency is the risk. The shared dependency is invisible to per-resource evaluation.
Why the Specification is Missing
This is the same structural gap described in the Missing Specification series: mechanism without meaning. The compliance framework says "encrypt at rest." It doesn't say "don't encrypt everything with the same key." The specification tells the team WHAT to do. It doesn't tell them HOW MANY shared dependencies is too many.
The missing declaration:
# What nobody writes:
dependency_policy:
kms_keys:
max_resources_per_key: 5
critical_resources_require_dedicated_key: true
cross_service_sharing: prohibited # S3 and RDS must not share a key
iam_roles:
max_functions_per_execution_role: 3
production_functions_require_dedicated_role: true
vpcs:
max_services_per_vpc: 10
critical_services_require_dedicated_subnet: true
If this declaration existed, a tool could evaluate it: "This KMS key is shared across 23 resources, exceeding the maximum of 5." The finding would be specific, actionable, and quantified. Without the declaration, the team doesn't know they have a problem until the key fails and 23 resources go down.
Stewart Brand's Shearing Layers
The common mode failure pattern is a shearing layer violation. The dependency (KMS key) changes at a different rate than the resources that use it.
KMS key policy (changes rarely — key management is not on the sprint board)
→ resources using the key (change frequently — new buckets, new databases, new volumes)
→ the count of resources sharing the key (grows monotonically — resources are added, never migrated to a new key)
The dependency is static. The resource count grows. The gap between them is the blast radius and it grows monotonically because migrating an encrypted resource to a new key is expensive (decrypt with old key, re-encrypt with new key, update all references). Nobody does it unless forced. So the count only goes up.
This is the same pattern as IAM privilege creep: permissions are granted and never revoked because revoking might break something. Dependencies are shared and never separated because separating is expensive. In both cases, the risk accumulates silently because the system provides no signal that it's accumulating. The resource works fine with a shared key. It works fine with a dedicated key. The system doesn't care. The system doesn't distinguish between "encrypted with a dedicated key" and "encrypted with a key shared by 22 other resources." Both pass the audit.
Graph Analysis
The evaluation requires graph analysis not per-resource property checks. A per-resource check sees: "this bucket is encrypted with key X." A graph analysis sees: "key X is referenced by 23 resources across 4 services, and if key X becomes unavailable, the blast radius is 23 resources."
The check is a group-by-and-count operation on the dependency graph:
For each dependency type (KMS key, IAM role, VPC, security group):
1. Collect all resources that reference this dependency
2. Group by dependency identifier (ARN or ID)
3. Count resources per dependency
4. Flag when count exceeds threshold
5. Report: which dependency, how many dependents, blast radius
The output:
FINDING: Common mode failure — KMS key shared across 23 resources
Dependency: arn:aws:kms:us-east-1:123456789012:key/abc-123
Type: KMS key
Dependents: 23
S3 buckets: 12 (bucket/data-*, bucket/logs-*, bucket/exports-*)
RDS databases: 6 (db/orders, db/users, db/analytics, ...)
EBS volumes: 3 (vol-abc, vol-def, vol-ghi)
Secrets Manager: 2 (secret/db-creds, secret/api-key)
Blast radius: if this key is disabled or compromised,
23 resources across 4 services lose access to their data.
Recommendation: create dedicated keys per service
(one for S3, one for RDS, one for EBS, one for Secrets Manager).
Minimum improvement: reduce from 1 shared key to 4 service-scoped keys.
This finding is invisible to every per-resource scanner. It's visible only to a tool that evaluates the graph of relationships between resources — the edges, not just the nodes.
The Broader Lesson
Common mode failure is the operational face of every thesis in the Missing Specification series. The team encrypted everything but never specified the isolation boundary. The team used IAM roles but never specified the sharing boundary. The team built in one VPC but never specified the blast radius boundary.
In each case, the mechanism was correct. The specification was missing. The risk accumulated silently because the system provides no signal that it's accumulating. Per-resource tools see the nodes and approve them. Nobody sees the edges.
The question is not "is this resource correctly configured?" Every resource is correctly configured. The question is "how many other resources fail when this dependency fails?" That question requires the graph. The graph requires compound analysis. Compound analysis requires an engine that reasons about relationships, not just properties.
Every compliance framework mandates encryption. No compliance framework mandates encryption isolation. The audit that checks "is it encrypted?" passes. The audit that checks "what's the blast radius of your encryption key?" doesn't exist because the tool to answer it hasn't existed.
Until now.
Top comments (0)