Skip to content

Fix SSH dashboard CSP and remote completion rendering#723

Open
jugol wants to merge 3 commits into
fathah:mainfrom
jugol:codex/fix-ssh-dashboard-csp-loopback
Open

Fix SSH dashboard CSP and remote completion rendering#723
jugol wants to merge 3 commits into
fathah:mainfrom
jugol:codex/fix-ssh-dashboard-csp-loopback

Conversation

@jugol

@jugol jugol commented Jun 18, 2026

Copy link
Copy Markdown

Summary

  • Allow loopback HTTP/WebSocket endpoints in the production renderer CSP header.
  • Keep the production CSP aligned with src/renderer/index.html, which already permits these loopback sources.
  • Treat message.complete as the canonical final assistant text in the dashboard event adapter.
  • Render remote/SSH dashboard assistant responses from final completion text only, while keeping local dashboard streaming unchanged.
  • Add regression tests for SSH dashboard loopback access, final completion replacement, and suppressed assistant deltas.

Why

SSH dashboard chat uses a local tunnel from the desktop app to the remote Hermes dashboard, for example:

127.0.0.1:<localPort> -> remote 127.0.0.1:<dashboardPort>

The renderer then opens the dashboard sidecar WebSocket through that local tunnel:

ws://127.0.0.1:<localPort>/api/ws?token=<redacted>

In production, the main process overrides the page CSP through webRequest.onHeadersReceived. That production CSP omitted loopback HTTP/WebSocket sources from connect-src, even though the renderer HTML CSP already includes them. Chromium can therefore block the intended SSH dashboard WebSocket before it reaches the tunnel, producing:

Could not connect to Hermes dashboard WebSocket

The CSP change is limited to loopback only:

http://127.0.0.1:*
http://localhost:*
ws://127.0.0.1:*
ws://localhost:*

That matches the SSH tunnel design while keeping the policy scoped to local desktop-owned endpoints.

Dashboard completion rendering

While validating the SSH dashboard path against a remote Hermes dashboard, I also hit a separate dashboard rendering issue: streamed message.delta text can differ from the final message.complete text. That is especially visible with non-English output when an interim partial fragment is malformed or incomplete.

Before this change, the adapter replaced the pending assistant bubble only when the final text started with the streamed text. If the streamed text did not match, it concatenated the partial stream with the final answer, so the UI could show a garbled prefix followed by the correct final answer.

message.complete is the authoritative final assistant response, so this PR now replaces the pending assistant bubble with that final text instead of appending it.

For remote/SSH dashboard sessions, the renderer now suppresses assistant message.delta bubbles and waits for message.complete. Local dashboard sessions keep the existing live assistant streaming behavior. This avoids showing transient malformed remote stream fragments while keeping the persisted/final transcript canonical.

Validation

  • npm test -- --run tests/dashboard-event-adapter.test.ts src/renderer/src/screens/Chat/hooks/useDashboardChatTransport.test.tsx
  • npm run build
  • npx vitest run tests/dashboard-csp.test.ts tests/askpass-security.test.ts
  • npm run typecheck:node

@jugol jugol marked this pull request as ready for review June 18, 2026 20:28

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@jugol jugol changed the title Fix SSH dashboard chat blocked by production CSP Fix SSH dashboard CSP and final completion rendering Jun 19, 2026

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@jugol jugol changed the title Fix SSH dashboard CSP and final completion rendering Fix SSH dashboard CSP and remote completion rendering Jun 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant