Skip to content

fix(encryption): remove aad parameter from decrypt methods - #1007

Open
realcodesiman wants to merge 2 commits into
mainfrom
fix/encryption-remove-decrypt-aad
Open

fix(encryption): remove aad parameter from decrypt methods#1007
realcodesiman wants to merge 2 commits into
mainfrom
fix/encryption-remove-decrypt-aad

Conversation

@realcodesiman

Copy link
Copy Markdown
Contributor

Summary

  • decryptText/decryptObject no longer take an aad parameter — they read encryptedData.aad off the stored blob instead, since only 1 of 22 production decrypt call sites derived and passed one, and duplicating that derivation between writer and reader was a correctness footgun (a drift between the two strings meant a hard decrypt failure) with no real payoff.
  • encryptText/encryptObject are unchanged and keep their aad parameter, since something still has to stamp the value at write time.
  • The one place that reads .aad directly — the appointment-token purpose check in verifyAppointmentToken — keeps its own aad parameter and pre-decrypt string comparison, since that guards token-purpose separation (schedule vs. cancel vs. webview tokens) rather than crypto authentication, and is now the sole mechanism enforcing it.
  • Reverts platform-credential's required-aad schema constraint and its rationale comment, since decrypt no longer needs a caller-derived aad to bind against — a blob with no aad is a legitimate case again, not an error.

Changes

  • packages/encryption/src/encryption.ts — drop aad param from decryptText/decryptObject; read encryptedData.aad internally; AES-GCM still authenticates the aad against the ciphertext/tag, so a tampered aad still fails, but an intact blob copied onto a different logical row is no longer detected (accepted trade-off)
  • packages/encryption/src/appointment-token-utils.ts — drop the now-removed 3rd arg from decryptObject; keep the purpose-label aad param and pre-decrypt comparison, with an updated comment noting it's now load-bearing alone
  • packages/business/src/platform-credential/service.ts_decrypt no longer derives a row-scoped aad; write paths (upsertForUser/upsertPlatform) still stamp one but drop the now-unnecessary credentialEncryptedSchema.parse() wrapper
  • packages/database/src/partials/credential.tsaad back to .optional(); kept the unrelated iv/text/tag length tightening, which mirrors encryptedDataSchema and turns malformed rows into clear parse failures at the storage boundary
  • packages/database/scripts/rotate-encryption-key.ts — drop the aad arg from the decrypt call; keep the aad derivation for re-encrypting rotated rows; keep the unparseable row warning bucket
  • Tests updated across encryption, database, and business packages to match the new signatures and invariants, including a new tampered-aad test locking in that the aad is still authenticated, not merely echoed

Test plan

  • pnpm --filter @chatbotx.io/encryption test — 27/27 passing
  • pnpm --filter @chatbotx.io/database test — 423/423 passing
  • pnpm --filter @chatbotx.io/business test — 1063/1063 passing
  • pnpm --filter worker test — 1562/1562 passing
  • pnpm --filter @chatbotx.io/encryption check-types, @chatbotx.io/database check-types, @chatbotx.io/business check-types, worker check-types — all clean
  • pnpm lint — clean
  • Repo-wide grep confirms no remaining 3-arg decryptObject/decryptText calls

decryptText/decryptObject now read the aad off the stored blob instead
of requiring the caller to reconstruct it, since only 1 of the 22
production decrypt call sites derived one and duplicating that string
between writer and reader was a correctness footgun with no real
payoff. encryptText/encryptObject keep their aad parameter to stamp
the value at write time.

The one place that read .aad directly (the appointment-token purpose
check) keeps its own parameter and comparison, since that guards token
purpose separation rather than crypto authentication and now does so
alone. Also reverts platform-credential's required-aad schema and its
now-inaccurate rationale, since decrypt no longer needs a caller-
derived aad to bind against.
@github-actions github-actions Bot added the bug Something isn't working as expected label Aug 20, 2026
Code-review follow-up for the aad-on-blob change: the row-scoped aad
template was hand-written in three writer sites (upsertForUser,
upsertPlatform, rotate-encryption-key.ts) and had to stay identical by
convention. Extract it into credentialAad in
packages/database/src/partials/credential.ts so a drift between writers
can no longer silently change what future rows are stamped with.

Also fixes the rotation script's stale "silently excluded" comment —
the unparseable-row warning it introduces is what makes that exclusion
loud.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working as expected

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant