Summary
specs/ARCHITECTURE.md and specs/SECURITY.md say public HTTP projections must not contain prompts or message text. The live dashboard API does.
Runtime adapters write a ~220 character user_message / user_input preview onto executions and series rows (user_prompt_preview() in token_meter/app.py). build_state() includes executions[-EXEC_LIMIT:]. dashboard_state_payload() strips trace and insights but does not strip those prompt fields. page.html then renders them in chart tooltips (s.user_message||s.user_input).
Claude, Codex, Cursor, and OpenCode adapters all populate this.
Impact
GET /session and GET /state return user prompt snippets to anyone who can hit loopback. Combined with the unauthenticated server (see the loopback/Host issue), this is a local data leak of agent prompts, not just cost telemetry.
MCP appears to allowlist this correctly. The gap is the browser HTTP surface.
Suggested fix
Strip user_message, user_input, and user_inputs at the HTTP projection boundary (dashboard_state_payload), and stop rendering prompt text in page.html. Keep language-signal counts if you want that feature; do not ship the matched utterance.
Summary
specs/ARCHITECTURE.mdandspecs/SECURITY.mdsay public HTTP projections must not contain prompts or message text. The live dashboard API does.Runtime adapters write a ~220 character
user_message/user_inputpreview onto executions and series rows (user_prompt_preview()intoken_meter/app.py).build_state()includesexecutions[-EXEC_LIMIT:].dashboard_state_payload()stripstraceandinsightsbut does not strip those prompt fields.page.htmlthen renders them in chart tooltips (s.user_message||s.user_input).Claude, Codex, Cursor, and OpenCode adapters all populate this.
Impact
GET /sessionandGET /statereturn user prompt snippets to anyone who can hit loopback. Combined with the unauthenticated server (see the loopback/Hostissue), this is a local data leak of agent prompts, not just cost telemetry.MCP appears to allowlist this correctly. The gap is the browser HTTP surface.
Suggested fix
Strip
user_message,user_input, anduser_inputsat the HTTP projection boundary (dashboard_state_payload), and stop rendering prompt text inpage.html. Keep language-signal counts if you want that feature; do not ship the matched utterance.