Found in PR #76 (fix/67-hkdf-key-derivation)
Severity: Major
In backend/src/lib/userApiKeys.ts, getEncryptionSecret() still falls back to API_KEYS_ENCRYPTION_SECRET and then SUPABASE_SECRET_KEY:
function getEncryptionSecret(): string {
const secret =
process.env.USER_API_KEYS_ENCRYPTION_SECRET ||
process.env.API_KEYS_ENCRYPTION_SECRET ||
process.env.SUPABASE_SECRET_KEY; // ← contradicts #74
PR #74 (fix/66-secret-key-reuse) explicitly requires USER_API_KEYS_ENCRYPTION_SECRET to be a distinct secret and removes the SUPABASE_SECRET_KEY fallback. PR #76 re-introduces that same fallback in the same file, meaning a deployment that sets only SUPABASE_SECRET_KEY (and not the dedicated secret) will silently use it as the HKDF input key — the same single-key-breaks-all vulnerability the original issue described.
Fix: Remove the fallback chain. Require USER_API_KEYS_ENCRYPTION_SECRET explicitly and throw if absent, matching the pattern used in PR #74's startup.ts.
Found in PR #76 (fix/67-hkdf-key-derivation)
Severity: Major
In
backend/src/lib/userApiKeys.ts,getEncryptionSecret()still falls back toAPI_KEYS_ENCRYPTION_SECRETand thenSUPABASE_SECRET_KEY:PR #74 (fix/66-secret-key-reuse) explicitly requires
USER_API_KEYS_ENCRYPTION_SECRETto be a distinct secret and removes theSUPABASE_SECRET_KEYfallback. PR #76 re-introduces that same fallback in the same file, meaning a deployment that sets onlySUPABASE_SECRET_KEY(and not the dedicated secret) will silently use it as the HKDF input key — the same single-key-breaks-all vulnerability the original issue described.Fix: Remove the fallback chain. Require
USER_API_KEYS_ENCRYPTION_SECRETexplicitly and throw if absent, matching the pattern used in PR #74'sstartup.ts.