unbridled-41 opened a new pull request, #4003:
URL: https://github.com/apache/rocketmq-dashboard/pull/4003

   Fixes #TBD-ISSUE.
   
   ## Problem / Evidence
   
   `GET /api/query-history/messages/{id}/results` returns the stored 
query-result snapshot for any record id with no ownership check. Record ids are 
sequential, so any authenticated user can enumerate 
`/api/query-history/messages/1../results` and replay another user's stored 
snapshots, which contain the topics, msgIds, tags, message keys, queue offsets, 
broker names and — notably — the `bornHost`/`storeHost` addresses of the 
clusters those users operate (`QueryHistoryService.buildResultSnapshot`, lines 
109-124).
   
   Every other read in the same service scopes to the authenticated user — 
`listMessageQueries` (`QueryHistoryService.java:184`), `listTraceQueries` 
(`:204`), and `summarize` (`:221-234`) all filter `queried_by = 
currentUsernameOrSystem()`, and the owner is stamped at insert (`:93`). The 
by-id results read added later (`selectById`, `:135`) is the only read that 
skips the boundary. The scoping contract was established by the merged fix for 
#2265 ("Query-history reads and summaries are scoped to the current 
authenticated user by default"); the results endpoint did not exist yet when 
that fix landed and never picked the boundary up.
   
   ## Root cause / Fix
   
   `getMessageQueryResults` fetched the row by id alone. Fix: read the row 
through the same owner-scoped `QueryWrapper` the other reads use (`.eq("id", 
id).eq("queried_by", currentUsernameOrSystem())`) and keep returning 404 for 
both missing and foreign records, so record existence is not leaked either. No 
admin bypass is added, matching the list paths.
   
   ## Priority & scoring
   
   PRIORITY 72 = impact 28 (authenticated cross-user disclosure of other 
operators' query metadata and internal broker/producer host addresses) + blast 
radius 12 (one endpoint, but all multi-user deployments with login required) + 
reproducibility 18 (deterministic, sequential ids, one request per record) + 
maintenance value 14 (aligns the last unscoped read with the service's own 
established boundary; one-line fix).
   
   FIX_CONFIDENCE 95 (the scoping pattern is already implemented and tested in 
the same class).
   
   ## Tests
   
   `mvn -B -ntp test 
-Dtest='QueryHistoryServiceTest,QueryHistoryControllerTest'`:
   
   - Before the fix, `getMessageQueryResultsHidesRecordsOwnedByOtherUsers` 
failed because the foreign-owned record (owner `bob`, current user `alice`) was 
returned instead of 404 — the defect reproduced.
   - After the fix: QueryHistoryServiceTest **12/12** (10 pre-existing + 2 new, 
including the owner-scoped wrapper SQL-segment assertion mirroring the existing 
`queried_by` captor pattern) and QueryHistoryControllerTest 4/4.
   - Full backend suite (`mvn -B -ntp test`): **Tests run: 2037, Failures: 3** 
— exactly the pristine-baseline set (AuthCorsIntegrationTest ×2, 
AliyunInstanceProviderTest ×1, identical messages); zero new failures; 2035 
baseline + 2 new tests.
   
   ## Risk
   
   Low. The normal UI flow only replays records from the requesting user's own 
history list, which is already owner-scoped, so no legitimate path loses 
access. Foreign or missing ids now return the same 404 as before for missing 
ids. Data contents, endpoints and response shapes are unchanged.
   


-- 
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