Keep every credential field out of JSON, and guard the rule library-wide

Fixkamo-shared-library
Shipped
September 17, 2026 at 3:33 AM UTC
Author
Kamo
Commit
f1c5d3b

Follow-up to 034378d2, which covered the columns NAMED as ciphertext. Read-only audits of origin/main in every repository found 61 more fields holding credentials with no Jackson guard. Three sets were in live responses: **************** .imapPassword (the encrypted IMAP login): GET /api/email/shared-mailboxes, /my-access, create and update return the entity to any session in the organization. User.password, .seedWords, .securityAnswer, .seedPhraseHash, **************** GET /api/security/org loads the caller's own User, so each org the caller owns serialized its owner in full. **************** the EHR exchange partner list and suspend return the entity. The rest were dormant (every endpoint builds a map or DTO) and one nesting or one returned entity away from publishing: AiProvider.apiKey; **************** **************** .configJson, and **************** which would nest them in the public org body; **************** **************** .password; **************** **************** access/refresh tokens on OrgEmailOAuthTokenEntity, **************** OrgOAuthToken, MemberVoipOAuthToken (+ jwtAssertion), OrgMeetingOAuthTokenEntity, ThirdPartyIntegration (+ webhookSecret); **************** RetailProviderConfig.apiKey, .apiSecret, .accessToken, .webhookSecret; PublicChatVisitor.sessionToken; **************** and the token and code hashes on EmailVerificationToken, PasswordResetToken (tokenShortHash IS the emailed reset code), UserDeviceToken, UserEmailChangeRequest, RecoverySession, PatientPortalSession, PatientPortalInvitation, QuoteShareLink, EsignEnvelopeRecipient, AccountVerificationCode, SmsOtp and MfaRecoveryCode. All are now @JsonIgnore. Checked for each before changing it: no request body binds the entity, nothing reads it with **************** no JSON cache, Redis or NATS transfer carries it, and no client in any repository reads the property. @JsonIgnore rather than WRITE_ONLY, so no request body can plant a password hash. **************** scans every persistent type the way **************** does: a text field whose name says password, secret, apiKey, access/refresh token, jwt, credential, seed words, security answer, private or signing key, or token/code hash, plus six credentials named otherwise, must be @JsonIgnore or WRITE_ONLY. Three names that only look like credentials are listed with the reason (two vault secret NAMES and a webinar join code). Run against origin/main it fails listing exactly the 59 name-matched fields above. A library fix ships per service: emailservice and securityservice are rebuilt with this for the live exposures.

All changes

Like what you see shipping?

All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.

Start Free ForeverView Pricing