fix(security): add authorization and input validation for menu and preferences#95
Open
JonasBaeumer wants to merge 3 commits into
Open
fix(security): add authorization and input validation for menu and preferences#95JonasBaeumer wants to merge 3 commits into
JonasBaeumer wants to merge 3 commits into
Conversation
…eferences Closes #91 - Verify intent ownership before cancel/card operations in Telegram menu (menu_cancel_confirm, menu_cancel_do, menu_card_cancel now require the intent's userId to match the requesting user's id) - Validate CardCancelPolicy enum value before casting from raw callback payload - Add userAuthMiddleware + ownership check to PATCH /v1/users/:userId/preferences, and write a PREFERENCES_UPDATED audit event on success - Guard undefined chatId/messageId in callbackHandler before menu dispatch instead of using non-null assertions
- Add promptMessageId to PrefSession interface - Use CardCancelPolicy enum instead of string literals - Move CancelCardJob to contracts and add QUEUE_NAMES constants - Replace duplicate ACTIVE_INTENT_STATUSES arrays with ACTIVE_STATES - Tighten ReconciliationReport types (PotStatus, cardStatus union)
52b5976 to
fb2aeec
Compare
refactor(contracts): type system and contract cleanup (#92)
georgyia
reviewed
Apr 14, 2026
georgyia
left a comment
Collaborator
There was a problem hiding this comment.
This is very close to merge — the security intent/ownership + validation changes look correct.
Small blockers to address before merge:
tests/integration/telegram/menuHandler.test.tshas 1 failing assertion: it expects a generic “went wrong” string, but the handler now returns the specific⚠️ Intent not found.message. Please update the expectation so the suite is green.- The same integration suite is gated on
STRIPE_SECRET_KEYeven though it mocks Telegram/BullMQ and only needs Postgres+Redis. Removing that gating will ensure these security tests actually run in CI/dev environments.
Once those two are fixed, I’m happy to approve.
16 tasks
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.
Closes #91
Summary
menu_cancel_confirm,menu_cancel_do, andmenu_card_cancelnow run after the user lookup and verifyintent.userId === user.idbefore acting. Forged or replayed callback payloads from other users get an error menu instead.menu_pref_policyvalidates the payload againstObject.values(CardCancelPolicy)before casting, preventing invalid values from being written to the DB.PATCH /v1/users/:userId/preferencesnow requires a valid Bearer token (userAuthMiddleware) and a matchinguserId. Returns 401 without auth, 403 for a different user. Writes aPREFERENCES_UPDATEDaudit event on success.chatId!/messageId!non-null asserts with an explicitif (chatId === undefined || messageId === undefined) return;guard to prevent silent runtime crashes on inline keyboard callbacks.Test plan
npm test -- --testPathPattern=tests/unitCardCancelPolicypayload → error shown, no DB writedocker compose up -d && npm run test:integration -- --testPathPattern=telegram/menuHandler