Part of #294.
Repo(s): webprotege-event-history-service (primary)
Problem (plain language)
There are two ways the browser gets project changes: the live WebSocket, and a fallback request that reads the permanent change archive. The WebSocket path correctly checks "are you allowed to view this project?" before letting you listen. The fallback path does not check anything.
That means any logged-in user can ask the archive for the change history of any project — just by supplying its ID — and receive it, including what was added, removed, renamed, and commented, regardless of whether they're permitted to open that project. This is a data-exposure hole, and the two paths disagreeing about who's allowed to see what is exactly the kind of gap that's easy to miss.
Suggested solution
Make the history-query handler enforce the same view-permission check the WebSocket subscription already uses. Concretely, the handler that answers the project-events query should require VIEW_PROJECT on the requested project (it currently implements the plain, unauthenticated handler type instead of the authorized one).
While here: the dispatch layer logs a user's access token on one permission-denied path — scrub that too, since it's the same class of concern.
Done when
- A user without view permission on a project receives a permission error (not data) when requesting that project's events through the fallback/polling path.
- A user with view permission still gets their events.
- No access tokens appear in logs.
Priority
Do this first. It's independent of the rest of the epic and it's a live exposure.
Part of #294.
Repo(s):
webprotege-event-history-service(primary)Problem (plain language)
There are two ways the browser gets project changes: the live WebSocket, and a fallback request that reads the permanent change archive. The WebSocket path correctly checks "are you allowed to view this project?" before letting you listen. The fallback path does not check anything.
That means any logged-in user can ask the archive for the change history of any project — just by supplying its ID — and receive it, including what was added, removed, renamed, and commented, regardless of whether they're permitted to open that project. This is a data-exposure hole, and the two paths disagreeing about who's allowed to see what is exactly the kind of gap that's easy to miss.
Suggested solution
Make the history-query handler enforce the same view-permission check the WebSocket subscription already uses. Concretely, the handler that answers the project-events query should require
VIEW_PROJECTon the requested project (it currently implements the plain, unauthenticated handler type instead of the authorized one).While here: the dispatch layer logs a user's access token on one permission-denied path — scrub that too, since it's the same class of concern.
Done when
Priority
Do this first. It's independent of the rest of the epic and it's a live exposure.