fix(dashboard): guide users to manual token auth when delivery channels fail#72802
Conversation
Greptile SummaryAdds a CVE-safe recovery hint to Two P2 observations worth considering before merging:
Confidence Score: 4/5Safe to merge; only P2 UX and coverage concerns, no runtime defects introduced. The change is small and well-targeted. No P0 or P1 bugs were found. The two P2 observations (missing fragment key name in hint, and double-hint in --no-open + clipboard-fail path) are UX and coverage issues, not correctness defects. CVE safety contract is preserved by both the implementation and the updated test suite. No files require special attention; src/commands/dashboard.ts lines 95–99 are the only new logic and both concerns relate to that block. Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/commands/dashboard.ts
Line: 95-99
Comment:
**Hint fires in `--no-open` + clipboard-fail path too**
When a user explicitly passes `--no-open`, `opened` is always `false` (never assigned in the `noOpen` branch), so if clipboard also fails, this block fires alongside the existing `--no-open` hint ("Browser launch disabled (--no-open). Use the URL above."). The user sees two partially contradictory messages: one telling them to use the bare URL above, and one telling them to manually construct the fragment URL. The existing test at line 201 doesn't assert absence of the new hint, so this goes undetected.
If the intent is for the hint to fire in the `--no-open` scenario as well (the PR description says it does), it would be worth adding a test covering that scenario explicitly, and confirming the two messages together make sense.
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: src/commands/dashboard.ts
Line: 95-99
Comment:
**Hint omits the URL fragment key name**
The message says "append your gateway token… as a URL fragment" but doesn't name the key (`token`). A headless user who hasn't seen the source will need to guess or consult docs to construct the correct fragment. The CVE constraint prohibits logging an actual secret value, but logging only the key name — with an explicit placeholder and no real value — carries no credential risk and would not trigger the existing CVE assertions.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix(dashboard): guide users to manual to..." | Re-trigger Greptile |
|
Addressed both P2 observations in commit P2-1 — fragment key name: the hint now names the URL fragment key ( P2-2 — double hint in Test coverage updated:
All CVE regression tests still pass; 11/11 in |
|
Thanks for the QC review. Both non-blocking suggestions were independently raised by @greptile-apps and addressed in commit
|
|
Both addresses look correct. The The The split of the old LGTM. No further concerns. Tip: You can customize Greptile's behavior for this repo with Re-review progress:
|
1204cc6 to
f6d0f71
Compare
|
Codex review: needs maintainer review before merge. Summary Reproducibility: yes. Source inspection gives a high-confidence path: configure a literal gateway.auth.token or OPENCLAW_GATEWAY_TOKEN, make clipboard delivery fail, and make browser opening unavailable or pass --no-open; current main logs the bare dashboard URL without token-source or fragment-key recovery guidance. Next step before merge Security Review detailsBest possible solution: Land this focused dashboard-command fix after maintainer review and exact-head validation, preserving token redaction while giving headless and WSL users a manual auth path. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection gives a high-confidence path: configure a literal gateway.auth.token or OPENCLAW_GATEWAY_TOKEN, make clipboard delivery fail, and make browser opening unavailable or pass --no-open; current main logs the bare dashboard URL without token-source or fragment-key recovery guidance. Is this the best way to solve the issue? Yes. The proposed fix stays in src/commands/dashboard.ts, fires only when tokenized delivery failed, deduplicates the --no-open fallback, and preserves the existing log-redaction contract with regression tests. Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 9eed48fde5a9. |
The previous run failed on src/cli/gateway-cli/run.option-collisions.test.ts
("does not write startup failure bundles for expected gateway lock conflicts")
with a known mock-timing race; this PR touches only src/commands/dashboard*.
Empty commit to retrigger CI.
Summary
openclaw dashboardcannot deliver the token-authenticated URL via either clipboard or browser auto-open, the user is now logged a CVE-safe self-recovery hint pointing toOPENCLAW_GATEWAY_TOKENandgateway.auth.token.#token=fragment marker is ever written to runtime logs — the existing CVE regression tests (dashboard.links.test.ts:101,:144) continue to enforce that contract on the success and SSH paths.Fixes #72081.
Why
The reporter ran
openclaw dashboardon WSL2 OpenEuler and saw onlyDashboard URL: http://...(no token). Both delivery channels — clipboard and browser auto-open — fail in many WSL/headless/SSH environments. The previous fix (eaf6d3c146, commitfix(dashboard): keep bearer token out of runtime logs) correctly removed the token from logs to remediate a CVE, but it didn't account for the case where neither clipboard nor browser succeeds — leaving headless users stranded with no path to authenticate.This change preserves the CVE fix exactly. It only adds a guidance hint when the delivery actually fails, telling the user where their token lives so they can manually append it as a URL fragment. The token itself never enters the log stream.
Why this scope
#token=substring (which the existing CVE tests forbid). It logs only the well-known config/env names.src/commands/dashboard.tsand its test — no shared SDK seam, no plugin runtime, no security helper changes.!copied && !opened && includeTokenInUrlcovers both--no-open + clipboard failand the defaultclipboard fail + browser failpaths.Test plan
pnpm test src/commands/dashboard.links.test.ts src/commands/dashboard.test.ts— 14/14 passing (10 indashboard.links.test.tsincluding new + 2 CVE regression tests, 4 indashboard.test.ts)pnpm check:changed— typecheck, lint, cycles, webhook/auth/pairing guards all cleanAI-assisted
Built with Claude Code (Opus 4.7, 1M context). Lightly tested — unit and changed-lane gates pass; live behavior on a real WSL/headless system not directly verified. I understand what the code does: see "Why" above.
🤖 Generated with Claude Code