# Dev/staging use different keys than prod

- **Pattern:** `ab-001433` (`finserv-encryption.pci-alignment.environment-specific-keys`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001433
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001433)

## Why it matters

CWE-321 (hard-coded cryptographic key) covers key reuse across environments as much as literal key embedding: when dev and prod share an encryption key, a developer database compromise — a much lower-bar attacker target — exposes the key that also decrypts production data. NIST SC-12 requires that key management procedures account for environment lifecycle boundaries. Cross-environment key sharing also violates the broader key-management lifecycle expectations in PCI-DSS v4.0 Requirement 3.7 — dev/prod key separation is the only way trust boundaries remain meaningful under those procedures. Environment-specific keys constrain the blast radius of a dev credential compromise to the dev environment only.

## Severity rationale

Low because exploiting shared keys requires developer credential access in addition to database access, but the control gap converts a dev breach into a prod data exposure.

## Remediation

Use environment-specific KMS key IDs for each environment, managed through environment variables that differ per deployment target. In your deployment pipeline:

```typescript
// src/lib/kms.ts — environment key selection at init time
const KMS_KEY_ID = (() => {
  const env = process.env.NODE_ENV;
  if (env === 'production') return process.env.AWS_KMS_KEY_ID_PROD!;
  if (env === 'test') return process.env.AWS_KMS_KEY_ID_TEST!;
  return process.env.AWS_KMS_KEY_ID_DEV!;
})();

if (!KMS_KEY_ID) throw new Error('KMS_KEY_ID not configured for environment');
```

In CI/CD, store `AWS_KMS_KEY_ID_PROD`, `AWS_KMS_KEY_ID_STAGING`, and `AWS_KMS_KEY_ID_DEV` as separate secrets in your CI secrets manager (GitHub Actions, Vercel Environment Variables). Add a pre-deploy assertion that the key ID matches the expected ARN prefix for the target environment — fail the deploy if they don't match.

## Detection

- **ID:** `environment-specific-keys`
- **Severity:** `low`
- **What to look for:** Count all environment configurations and enumerate the encryption key identifiers per environment. Quote the actual KMS key ID or environment variable names found. Verify at least 2 distinct key identifiers exist (dev vs. prod minimum). Using the same key across environments does not count as pass.
- **Pass criteria:** At least 2 distinct encryption keys are configured for different environments (minimum: dev and prod must differ). Count all environments — report the ratio even on pass (e.g., "3 distinct KMS keys: dev, staging, prod — 0 shared keys").
- **Fail criteria:** Same encryption key used across environments (0 distinction between dev and prod), or only 1 key identifier found.
- **Skip (N/A) when:** Never — environment-specific keys are a security best practice.
- **Detail on fail:** `"1 KMS key found across all environments — dev and prod share AWS_KMS_KEY_ID"` or `"0 environment distinction: same ENCRYPTION_KEY in .env.development and .env.production"`
- **Remediation:**
  - Configure environment-specific keys:
    ```typescript
    // Use environment-specific KMS keys
    const kmsKeyId = process.env.NODE_ENV === 'production'
      ? process.env.AWS_KMS_KEY_ID_PROD
      : process.env.AWS_KMS_KEY_ID_DEV;
    ```
  - Or use Vault environments:
    ```bash
    # Vault paths per environment
    vault kv get secret/prod/encryption-key
    vault kv get secret/staging/encryption-key
    vault kv get secret/dev/encryption-key
    ```
  - Verify in deployment:
    ```bash
    # Pre-deployment check
    if [ "$ENVIRONMENT" == "prod" ] && [ "$AWS_KMS_KEY_ID" != "$AWS_KMS_KEY_ID_PROD" ]; then
      echo "ERROR: Production must use prod KMS key"
      exit 1
    fi
    ```

## External references

- cwe CWE-321
- nist SC-12

Taxons: cryptography-and-secrets

HTML version: https://auditbuffet.com/patterns/ab-001433
