All Docs
FeaturesCalmony Sanctions MonitorUpdated March 11, 2026

Security Advisory: SEC-06 — Cryptographic Failures in Field Encryption

Security Advisory: SEC-06 — Cryptographic Failures in Field Encryption

Version: 0.1.39
Severity: High
OWASP Category: A02:2021 – Cryptographic Failures
File: src/lib/encryption.ts


Background

The sanctions screening platform encrypts personally identifiable information (PII) — including individual names and dates of birth — before storing it in the database. This encryption is handled by encryptField() in src/lib/encryption.ts, which relies on the ENCRYPTION_SECRET environment variable to derive its encryption key.

The Vulnerability

Prior to v0.1.39, encryptField() contained a silent fallback: if ENCRYPTION_SECRET was not set, or if its value contained the string 'dummy', the function would return the input as plaintext rather than raising an error. The only signal to operators was a console.log message — no exception was thrown and the application continued to run.

This created two concrete risks:

  1. Misconfigured production deployments — If ENCRYPTION_SECRET was accidentally omitted from a production environment's configuration (e.g. a missing secret in a container orchestration platform), all PII ingested after that point would be stored unencrypted with no hard failure to alert the team.

  2. Typo matching — The 'dummy' check was a substring match, meaning a legitimately set production key that happened to contain the word dummy anywhere in its value would silently disable encryption.

What Changed in v0.1.39

1. Production startup guard

A startup check now runs on application initialisation. If NODE_ENV is production and ENCRYPTION_SECRET is absent, the application throws immediately and refuses to start. This turns a silent misconfiguration into an explicit, unavoidable failure.

2. Minimum key length enforcement

The 'dummy' string check has been removed. Instead, the library enforces a minimum key length of 32 characters. Any ENCRYPTION_SECRET shorter than this threshold is rejected. This is a deterministic, auditable rule that does not depend on the content of the key.

3. Explicit ENCRYPTION_ENABLED flag

For environments where encryption is intentionally disabled (e.g. local development, CI pipelines), a new ENCRYPTION_ENABLED environment variable provides an explicit opt-out. This makes the disabled state a deliberate, visible configuration choice rather than a consequence of an absent secret.

Operator Action Required

Before upgrading to v0.1.39 in any production environment, verify the following:

CheckRequirement
ENCRYPTION_SECRET is setMust be present; application will not start without it in production
ENCRYPTION_SECRET lengthMust be 32 characters or longer
Dev / CI environmentsSet ENCRYPTION_ENABLED=false explicitly if encryption is intentionally off

Warning: If you upgrade without a valid ENCRYPTION_SECRET configured, your production application will fail to start. This is intentional — it is safer to fail loudly than to run with unencrypted PII.

Checking Your Current Configuration

Verify your secret meets the minimum length requirement before deploying:

# Check length of your current secret (should output 32 or more)
echo -n "$ENCRYPTION_SECRET" | wc -c

Generate a compliant secret if you do not already have one:

# Generate a 32-byte cryptographically random secret, base64-encoded
openssl rand -base64 32

Summary

This fix closes a cryptographic failure where a missing or loosely matched ENCRYPTION_SECRET would cause PII to be silently stored in plaintext. The corrected implementation follows the principle of failing fast and loudly, and removes ambiguous heuristics in favour of explicit, enforceable rules.