Security Fix: Encrypted Token Adapter No Longer Falls Back to Plaintext
Security Fix: Encrypted Token Adapter No Longer Falls Back to Plaintext
Version: 1.0.169
Severity: High
Component: src/lib/auth/encrypted-adapter.ts, src/instrumentation.ts
Background
This application connects to the HMRC Making Tax Digital API using OAuth. As part of that flow, HMRC issues OAuth tokens — access_token, refresh_token, and id_token — which are stored in the application's accounts database table. Because these tokens grant access to users' HMRC accounts and tax data, they must be stored encrypted at rest.
The encryptedDrizzleAdapter exists specifically to enforce this: it wraps the standard Drizzle database adapter and encrypts token fields using a key supplied via the HMRC_TOKEN_ENCRYPTION_KEY environment variable before any write to the database.
The Vulnerability
Prior to this release, the encryptedDrizzleAdapter contained a silent fallback behaviour: if HMRC_TOKEN_ENCRYPTION_KEY was not set, the adapter would proceed normally but skip encryption entirely — writing token values to the database in plaintext. The only indication of this failure mode was a console.warn log message.
This created a meaningful risk in practice:
- An accidentally rotated, deleted, or missing environment variable would result in all subsequent OAuth tokens being stored unencrypted.
- The application would continue to start and function normally, giving no visible sign that anything was wrong.
- In a containerised or serverless deployment,
console.warnoutput may not be monitored, meaning the issue could persist undetected.
Any user who authenticated with HMRC after the key was unset would have their tokens exposed in the database in plaintext.
The Fix
1. Plaintext fallback removed
The conditional logic in encryptedDrizzleAdapter that allowed operation without an encryption key has been removed. The adapter now always requires a valid key. If a key is not available at the time a token write is attempted, the adapter throws an error rather than proceeding.
2. Boot-time validation added
A startup check has been introduced in src/instrumentation.ts that runs before the application accepts any traffic. This check:
- Asserts that
HMRC_TOKEN_ENCRYPTION_KEYis present in the environment. - Validates that the key is correctly formatted for use with the encryption implementation.
- Throws a fatal error and halts application startup if either condition is not met.
This means misconfiguration is caught immediately at boot, rather than silently at runtime during a user authentication flow.
Impact on Deployments
⚠️ This is a breaking change for misconfigured environments.
If HMRC_TOKEN_ENCRYPTION_KEY is not set in your environment, the application will now refuse to start. This is intentional. A deployment that would previously have started successfully (but stored tokens insecurely) will now fail fast with a clear error.
Before upgrading to v1.0.169, confirm the following in every environment:
HMRC_TOKEN_ENCRYPTION_KEYis set and non-empty.- The key meets the format requirements expected by the encryption implementation (refer to your environment configuration documentation).
- Any existing plaintext tokens stored during a period when the key was unset should be identified, invalidated, and re-issued — affected users will need to re-authenticate with HMRC.
Checklist for Operators
-
HMRC_TOKEN_ENCRYPTION_KEYis present in all deployment environments - Key format has been validated
- Application starts successfully after deploying v1.0.169
- Audit logs reviewed to determine if any tokens were written without encryption prior to this fix
- Affected users (if any) notified and prompted to re-authenticate