ChinmayOnGithub / ChinmayOnGithub/tracker

[CRITICAL][Security] Prevent cross-account data leakage when switching users

Closed
#57 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

critical security
Dominant language
TypeScript
Stars
0
Forks
0
Avg merge
16m
Merged PRs (30d)
3

Description

Problem

A serious multi-user data-isolation bug has been observed in the live application.

After switching from the owner/admin account to another user account, the Calendar UI can display the owner's Journal content.

Observed behavior:

  • The Calendar Day Planner shows the Journal tab for the logged-in user.
  • The displayed Journal Entry content is content previously written from the owner/admin account.
  • The affected account should only ever see its own journal data.

This is a cross-account privacy/data-isolation issue and is launch-blocking.

Code findings

The server-side journal queries inspected so far are user-scoped:

  • app/actions/journal.ts uses userId: user.id.
  • modules/calendar/services/CalendarAggregationService.ts receives a userId and scopes journal queries to it.
  • app/actions/queries.ts scopes fetchCalendarDataAction() journal queries to loggedUser.id.

Therefore the investigation must not assume the database query itself is the only problem.

A concrete client-side isolation risk was found in components/CalendarWrapper.tsx:

  1. Calendar data is stored in the global client useStore().
  2. The store is not visibly keyed by authenticated user/session.
  3. Calendar background revalidation uses the global request-deduplication key:
    calendar:data
  4. The wrapper only performs the background refresh when the calendar cache is stale or the template store is empty.
  5. There is no demonstrated session/user identity boundary in this flow that guarantees data from the previous account is cleared before another account can render it.

This can allow stale in-memory data from one authenticated account to remain visible after logout/login or account switching.

Required investigation

Audit the complete authenticated-user data lifecycle for:

  • login
  • logout
  • account switching
  • session refresh
  • useStore() initialization/reset
  • CalendarWrapper
  • CalendarDataContext
  • requestDeduplicator
  • all cache metadata
  • dashboard initialization
  • journal initialization
  • calendar initialization
  • any client persistence/localStorage/sessionStorage/IndexedDB
  • Next.js router transitions that occur without a full page reload

Determine exactly how owner data can survive into another user's client state.

Required fix

Implement a canonical session-scoped client data boundary.

At minimum:

  • client stores must be associated with the authenticated user/session identity;
  • user logout must clear all private in-memory module state;
  • switching accounts must invalidate the previous user's cached data before rendering the new account;
  • request deduplication/cache keys for authenticated private data must include the effective user/session scope or otherwise be guaranteed to be isolated;
  • stale data must never be rendered while the new user's authorization/session is being resolved;
  • server-side ownership checks must remain authoritative;
  • do not solve this by merely hiding the UI;
  • do not copy or merge data between user stores.

Audit other modules for the same risk, not just Journal/Calendar:

  • Activities
  • Journal
  • Notes
  • Leave
  • Weight
  • Links
  • Vault/Documents
  • Calendar
  • Dashboard
  • Search
  • Settings

Regression tests

Add tests proving:

  1. User A creates a unique journal entry.
  2. User B creates a different unique journal entry.
  3. User A logs out.
  4. User B logs in in the same browser/session context.
  5. User B never sees User A's journal content.
  6. User B's calendar/dashboard state contains only User B's data.
  7. Switching B -> A -> B cannot leak stale data.
  8. Request deduplication cannot return User A's private response to User B.
  9. Logout clears private client state.
  10. A fresh login after account switching starts from the authenticated user's data scope.

Add equivalent cross-user regression coverage for other private modules where the same store/cache architecture is used.

Acceptance criteria

  • Zero cross-account private content can appear after account switching.
  • Journal content is always scoped to the authenticated user.
  • Calendar Day Planner never displays another user's journal.
  • Client caches and in-memory stores are session/user isolated.
  • Request deduplication cannot cross account boundaries.
  • Logout/account switching invalidates the previous user's private state.
  • Automated regression tests reproduce and prevent the original failure.
  • No weakening of server-side authorization is introduced.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Trace the authenticated data lifecycle through app/actions/journal.ts, app/actions/queries.ts, components/CalendarWrapper.tsx, CalendarDataContext, useStore(), and requestDeduplicator, starting with login, logout, and account switching. Add cross-user regression coverage for Journal and Calendar, then extend it to modules using the same store/cache architecture. Done means logout and switching invalidate private state, deduplication cannot cross users, and no stale private content renders.

Written by the indexing model from the issue text.

Assessment

Tech stack
next.js, typescript
Domain
authentication, full-stack, security, testing-qa
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.