Encryption keys stored separately from data in dedicated KMS
Why it matters
CWE-321 (use of hard-coded cryptographic key) describes the failure where the key and the data it protects are co-located — making the key trivially recoverable from anyone who can read the codebase, a git history export, or an environment variable committed to source control. NIST SC-12 requires that cryptographic keys be generated, distributed, stored, and destroyed through a formal key management process. PCI-DSS 4.0 Req-3.7 requires split knowledge and dual control for key custodianship. An encryption key stored next to the data it encrypts — whether in a .env committed to git, config/keys.json, or hardcoded in source — means any code read gives an attacker both the ciphertext and the key to decrypt it. OWASP 2021 A02 explicitly cites key co-location as a cryptographic failure root cause.
Severity rationale
High because a key stored alongside encrypted data completely defeats encryption — any attacker with codebase read access can decrypt all protected records without brute force.
Remediation
Migrate encryption key loading to a dedicated KMS. AWS KMS, GCP Cloud KMS, and Azure Key Vault all provide key material that never leaves the service — your application receives ciphertext, not the raw key. For AWS:
// src/lib/kms.ts
import { KMSClient, EncryptCommand, DecryptCommand } from '@aws-sdk/client-kms';
const client = new KMSClient({ region: process.env.AWS_REGION });
export async function kmsEncrypt(plaintext: string): Promise<string> {
const cmd = new EncryptCommand({
KeyId: process.env.AWS_KMS_KEY_ID!,
Plaintext: Buffer.from(plaintext),
});
const result = await client.send(cmd);
return Buffer.from(result.CiphertextBlob!).toString('base64');
}
export async function kmsDecrypt(ciphertext: string): Promise<string> {
const cmd = new DecryptCommand({
CiphertextBlob: Buffer.from(ciphertext, 'base64'),
});
const result = await client.send(cmd);
return Buffer.from(result.Plaintext!).toString('utf8');
}
Remove all key material from the codebase. If a key was ever committed to git, rotate it immediately — git history is permanent.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Financial Data Encryption Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-321 — Use of Hard-coded Cryptographic Key
- owasp:2021 · A02 — Cryptographic Failures
- nist:rev5 · SC-12 — Cryptographic Key Establishment and Management
- pci-dss:4.0 · Req 3.7 — Key management policies and procedures for cryptographic keys
Taxons
History
- 2026-04-18·v1.0.0·Initial import from finserv-encryption·automated