Repository navigation
fix(stack,supabase,prisma): keep plaintext search terms out of errors and logs - #1554
Draft
cipherstash-agent wants to merge 2 commits into
Draft
cipherstash-agent wants to merge 2 commits into
cipherstash-agent wants to merge 2 commits into
Conversation
… and logs The free-text needle guard (matchNeedleError) quoted the rejected search term, and the Supabase and Prisma wildcard errors quoted the rejected pattern. Supabase's query-level catch then logged the full message at error level, the default STASH_STACK_LOG level, so a short needle reached production logs. Callers also commonly log thrown errors, and the Prisma pattern can be arbitrarily long. The three messages now report the term's length in codepoints instead of the term. The Supabase catch logs only the failure's kind (error class, plus the encryption error's type and code), since it sees errors from every layer and any of their messages may quote a value. The full message still reaches the caller in error.message. Fixes CIP-5161. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Jmn7pT73uHWFP7RKEikuh
…DB too Review follow-up. The DynamoDB adapter's handleError logged the full error message at error level, the same leak the Supabase catch had: the message can quote a plaintext value from any layer below. The log-safe description moves to a shared describeFailure helper in adapter-kit, used by both adapters. Besides the error class it now keeps the fixed identifiers a failure carries (type, code, authCode, on the error or a nested encryptionError), so a PostgREST code or a token service refusal such as USAGE_LIMIT_EXCEEDED still reaches the log. Each must look like an identifier, so a field holding data is dropped. Also aligns the Supabase and Prisma wildcard error wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Jmn7pT73uHWFP7RKEikuh
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true |
🦋 Changeset detectedLatest commit: ba272d9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 11 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by CipherStash · project thread
Summary
Search terms on encrypted columns are plaintext the caller chose to protect, but three error messages quoted them, and the Supabase adapter logged the full message at
errorlevel (the defaultSTASH_STACK_LOGlevel). That broke the "plaintext is never logged" contract. Fixes CIP-5161.Changes
matchNeedleError(shared by the Drizzle, Supabase, Prisma and coreencryptQueryguards) reports the short needle's length, not the needle.like/ilikeand PrismaeqlMatchreport the pattern's length, not the pattern. Supabase's was not in the issue; it had the same problem.handleErrornow log the failure's kind instead of its message. Both catches see errors from every layer, and any of those messages can quote a value. The new shareddescribeFailurehelper (exported from@cipherstash/stack/adapter-kit) produces the description: the error class, plus anytype,codeandauthCodeon the error or on a nestedencryptionError. Each identifier must match^[\w.-]{1,64}$, so a field that holds data is dropped. The full message is still returned to the caller.@cipherstash/stack,@cipherstash/stack-supabaseand@cipherstash/stack-prisma.Verification
mainfor the expected reason (the term or the message appeared in the output):stack/__tests__/match-needle-guard.test.ts: "never echoes the search term"stack-prisma/test/v3/operator-lowering-v3-text-search.test.ts: "never echoes the rejected pattern"stack-supabase/__tests__/no-plaintext-in-errors.test.ts: short needle, like pattern, and logged failure kindstack/__tests__/dynamodb/resolve-decrypt.test.ts: "logs the failure kind and code, never the message"stack/__tests__/describe-failure.test.tscovers the helper.stack-drizzle: all passing.stack-prismav3: all passing.stack: everything passes except the tests that need the nativeprotect-ffibinding, which isn't built in this container (cjs-require,match-bloom-liveand the live-credential files).stack-supabase: everything passes exceptsupabase-declared-modeandsupabase-v3-factory, which need the native@cipherstash/authbinding. Those same failures happen on unchangedmainhere.Review notes
Errornow logs as justError, because there is no reliable way to tell a library message apart from one that quotes caller data. The caller still gets the full message on the returned error.selector-path.ts'sString(value)was raised in review and refuted. Only non-finite numbers (NaN,±Infinity) reach that branch, and they carry no data.Generated by Claude Code