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:
-
Misconfigured production deployments — If
ENCRYPTION_SECRETwas 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. -
Typo matching — The
'dummy'check was a substring match, meaning a legitimately set production key that happened to contain the worddummyanywhere 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:
| Check | Requirement |
|---|---|
ENCRYPTION_SECRET is set | Must be present; application will not start without it in production |
ENCRYPTION_SECRET length | Must be 32 characters or longer |
| Dev / CI environments | Set ENCRYPTION_ENABLED=false explicitly if encryption is intentionally off |
Warning: If you upgrade without a valid
ENCRYPTION_SECRETconfigured, 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.