From 763d353f5c520eb5f048ded69f903c8632e56b11 Mon Sep 17 00:00:00 2001 From: oyi77 Date: Tue, 21 Apr 2026 03:16:52 +0700 Subject: [PATCH] fix(encryption): return null on decryption failure to prevent sending encrypted tokens to providers - When decrypt() encounters a malformed encrypted value (invalid format), return null instead of the ciphertext - When decrypt() fails due to decryption error (wrong key, auth tag mismatch), return null instead of the ciphertext - This prevents encrypted tokens from being sent to upstream APIs - Fixes [400]: Improperly formed request errors when routing to Kiro and other providers with unavailable credentials - Updated test expectations to match the new correct behavior: decrypt returns null on any failure --- src/lib/db/encryption.ts | 9 ++++++--- tests/unit/db-encryption.test.ts | 8 +++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/lib/db/encryption.ts b/src/lib/db/encryption.ts index c26cd10624..4e0601f458 100644 --- a/src/lib/db/encryption.ts +++ b/src/lib/db/encryption.ts @@ -110,14 +110,16 @@ export function decrypt(ciphertext: string | null | undefined): string | null | console.warn( "[Encryption] Found encrypted data but STORAGE_ENCRYPTION_KEY is not set. Cannot decrypt." ); - return ciphertext; + // Return null instead of encrypted ciphertext to prevent sending encrypted tokens to providers + return null; } const body = ciphertext.slice(PREFIX.length); const parts = body.split(":"); if (parts.length !== 3) { console.error("[Encryption] Malformed encrypted value"); - return ciphertext; + // Return null instead of encrypted ciphertext to prevent sending malformed encrypted tokens to providers + return null; } const [ivHex, encryptedHex, authTagHex] = parts; @@ -134,7 +136,8 @@ export function decrypt(ciphertext: string | null | undefined): string | null | } catch (err: unknown) { const message = err instanceof Error ? err.message : String(err); console.error("[Encryption] Decryption failed:", message); - return ciphertext; + // Return null instead of encrypted ciphertext to prevent sending encrypted tokens to providers + return null; } } diff --git a/tests/unit/db-encryption.test.ts b/tests/unit/db-encryption.test.ts index 97b290f241..092743358f 100644 --- a/tests/unit/db-encryption.test.ts +++ b/tests/unit/db-encryption.test.ts @@ -66,7 +66,7 @@ test("connection field helpers encrypt and decrypt all supported credential fiel assert.deepEqual(decrypted, connection); }); -test("decrypt returns the original ciphertext when the value is malformed or the key is wrong", async () => { +test("decrypt returns null when the value is malformed or the key is wrong", async () => { process.env.STORAGE_ENCRYPTION_KEY = "task-304-secret-c"; const firstModule = await importFresh("src/lib/db/encryption.ts"); const encrypted = firstModule.encrypt("top-secret"); @@ -74,6 +74,8 @@ test("decrypt returns the original ciphertext when the value is malformed or the process.env.STORAGE_ENCRYPTION_KEY = "task-304-secret-d"; const secondModule = await importFresh("src/lib/db/encryption.ts"); - assert.equal(secondModule.decrypt(encrypted), encrypted); - assert.equal(secondModule.decrypt("enc:v1:not-valid"), "enc:v1:not-valid"); + // When decryption fails with wrong key, return null (not encrypted ciphertext) + // This prevents sending encrypted tokens to APIs + assert.equal(secondModule.decrypt(encrypted), null); + assert.equal(secondModule.decrypt("enc:v1:not-valid"), null); });