diff options
| author | tv <tv@krebsco.de> | 2026-11-08 14:13:05 +0000 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-08 15:26:03 +0100 |
| commit | 69a08327d24d08ba7a4e879116eeff60ac2a3874 (patch) | |
| tree | ca822e7efe7123c290fd7923034cd5123fe5584a /src/api/dashboard/dashboard.html | |
| parent | 5de2994c6d8f5f266d60b4febdf9252a035488ad (diff) | |
dashboard: hand over a token reading the member list only
Review finding 8, second part: opening another member's dashboard
handed it a token reading everything (READ_ALL). A member writes its
own dashboard URL, so a malicious one received a read-everything token
under the operator's identity: /admin/config, /admin/changes,
/admin/log and the rest, on every node the user reaches.
The token handed over now reads the member list only (READ_MEMBERS, as
sent to subscribed nodes), which is enough to draw the map; the user
logs in at the other dashboard to see more. With 1151 it lasts five
minutes and isn't refreshed past them.
Diffstat (limited to 'src/api/dashboard/dashboard.html')
| -rw-r--r-- | src/api/dashboard/dashboard.html | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/src/api/dashboard/dashboard.html b/src/api/dashboard/dashboard.html index d01639e..b80e0d2 100644 --- a/src/api/dashboard/dashboard.html +++ b/src/api/dashboard/dashboard.html @@ -2078,8 +2078,9 @@ function handOff(id, handed) { legend: !document.getElementById("legends").hidden, figures: [...open], document: [...documentOpen], - // A token reading only, for five minutes: the other node's login page begins a - // session with it (`login.html`), where the browser has none there. + // A token reading the member list only, for five minutes, enough for the map: the + // other node's login page begins a session with it (`login.html`), where the + // browser has none there. Whoever publishes the dashboard gets it: no more. token: handed || undefined, })); } @@ -2451,7 +2452,6 @@ addEventListener("keydown", event => { // opened in this page; else its halo flashes red, larger than usual, and "no dashboard" // rises from it in the same red, both fading out. This node's own: here already. const FLASH_MS = 1200; -const READ_ALL = [{ path: [], rights: ["read"] }, { path: ["_continuum"], rights: ["read"] }]; async function openDashboard(id) { const member = state.graph.members[id]; if (!member || member.self) return; @@ -2460,7 +2460,7 @@ async function openDashboard(id) { if (token) { try { handed = (await tokenCall("../auth/refresh", token.token, - { limit: READ_ALL, lifetime: 300 })).token; + { limit: READ_MEMBERS, lifetime: 300 })).token; } catch (_) { /* the other dashboard asks for a login then */ } } location.assign(member.dashboard.split("#")[0] + handOff(id, handed)); |
