unbridled-41 opened a new issue, #5921:
URL: https://github.com/apache/rocketmq-dashboard/issues/5921

   ### Studio Version
   branch: `rocketmq-studio` @ `7e7aa344` (the revision verified; the branch is 
based on it)
   deployed as: not required to reproduce (any multi-user Studio)
   
   ### Runtime Environment
   
   Reproduced with the frontend tests (`cd web && npx vitest run 
src/pages/ai/hooks/useComposerDraft.test.ts`); any browser.
   
   ### Connected RocketMQ Cluster
   
   Not involved.
   
   ### Describe the Bug
   
   The AI composer keeps unsent text in `sessionStorage` under one global key:
   
   ```ts
   export const COMPOSER_DRAFT_STORAGE_KEY = 
'rocketmq-studio-ai-composer-draft';
   ```
   
   `sessionStorage` is per tab and survives a client-side logout in that tab: 
logout only clears `localStorage` (`authStorage.clearAuthSession` removes the 
token and the user keys from `localStorage`), and nothing removes the draft key 
except an explicit send or clear. The next operator who signs in on the same 
tab therefore opens /ai with the previous operator's unsent prompt already in 
the composer, and can send it as their own - cluster addresses, topic and group 
names, whatever the first operator was mid-question about.
   
   The sibling client-side preferences already key their storage by the account 
for exactly this reason, and the hook's own design note explains the per-tab 
lifetime without ever addressing whose draft it is.
   
   ### Steps to Reproduce
   
   1. Sign in as operator A, open /ai, type a question but do not send it.
   2. Log out (client-side) and sign in as operator B in the same tab, then 
open /ai.
   3. The composer contains A's text.
      Red before the fix: `expected 'check the backlog on rmq-prod' to be ''`.
   
   ### What Did You Expect to See?
   
   The draft belongs to the account that typed it, and a different account 
starts with an empty composer.
   
   ### What Did You See Instead?
   
   The previous account's unsent text, ready to be sent.
   
   ### Evidence
   
   - `web/src/pages/ai/hooks/useComposerDraft.ts` (the key and the read/write 
helpers), `web/src/stores/authStorage.ts:57-62` (logout clears localStorage 
only), `web/src/stores/authStore.ts` (the account to scope by).
   - `cd web && npx vitest run src/pages/ai/hooks/useComposerDraft.test.ts` - 
the new case fails before the fix.
   
   ### Impact
   
   Cross-account disclosure of whatever the previous operator had typed but not 
sent, on a shared workstation tab, and the leaked text can be submitted under 
the new account.
   
   ### Acceptance Criteria
   
   - The draft is stored per account (user id when present, username 
otherwise), the anonymous case keeps working, and a regression test pins that a 
second account starts empty.
   
   **Corresponding PR:** #ISSUEPR#
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to