Why this matters
Strong cryptography and key management limits blast radius if memory or storage is exposed.
If PAN must be handled transiently, encrypt in memory with AES-256-GCM using a KMS/HSM-provided key, store only ciphertext or tokens, and zeroize plaintext buffers immediately. Rotate keys per policy. (PCI DSS 4.0 Req. 3)
Strong cryptography and key management limits blast radius if memory or storage is exposed.
Side-by-side examples engineers can pattern-match during review.
// ❌ plaintext PAN persisted
String pan = request.getParameter("pan");
save("cards", Map.of("pan", pan));SecretKey key = kms.fetchKey("pci-pan-key");
Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
byte[] iv = SecureRandom.getInstanceStrong().generateSeed(12);
c.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, iv));
byte[] ct = c.doFinal(panBytes);
Arrays.fill(panBytes, (byte)0); // zeroize
save("cards", Map.of("pan_ct", Base64.getEncoder().encodeToString(ct), "iv", Base64.getEncoder().encodeToString(iv)));Files.writeString(path, pan)Arrays.fill(panBytes,(byte)0)From the same buckets as this rule.
Never emit Primary Account Number (PAN) or Sensitive Authentication Data (SAD: CVV/CVC, full track data, PIN) to application or audit logs. Per PCI DSS 4.0 Req. 3 and 10, always mask PAN as first6last4 and fully redact SAD before logging.
Reject PRs adding real PAN/CVV in fixtures, seeds, or mocks. Only use Luhn-valid test PANs from the gateway or opaque tokens (e.g., tok_) and never include CVV. Add a check to fail if a PAN regex is matched. (PCI DSS data minimization)