fix: harden remote relay credentials and lifecycle - #136
Conversation
|
Addressed all independent review findings in
Regression coverage includes policy matrices, active CONNECTING reconnect vs Local verification: |
|
Follow-up review fixes are pushed in
Focused regressions now exercise malformed relay errors, mixed-case UUID leakage through Post-commit verification passed: |
848f1c8 to
77f87aa
Compare
Users are shown one canonical connector credential in the extension (https://relay.api.vibebrowser.app/mcp/<uuid>). That string could be pasted into Claude/ChatGPT connectors but not into the CLI, which forced users to learn a second transport URL for the same bearer capability. `--remote` (start, openclaw, browser CLI) and the MCP `set_remote` tool now accept it, deriving the relay target deterministically through the single shared normalizer `parseRemoteTarget`: https://host[/prefix]/mcp/<uuid> -> wss://host[/prefix] + <uuid> http://<loopback>[/prefix]/mcp/<uuid> -> ws://<loopback>[/prefix] + <uuid> Bare UUID and ws(s) relay URL forms are unchanged. All #136 hardening is preserved: valid UUID only, no credentials/query/ fragment, no non-loopback plaintext relay transport, and no bearer value in errors, logs, help text, or CLI output. Generic HTTP(S) URLs without the exact /mcp/<uuid> suffix are rejected. Tests: connector normalization matrix (self-hosted path prefixes, ports, loopback forms), malformed/hostile URL rejections with leak assertions, a live set_remote connect over the connector form, a browser-CLI status run through an http connector URL, and a packaged-CLI help gate. Refs #145, #130 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Users are shown one canonical connector credential in the extension (https://relay.api.vibebrowser.app/mcp/<uuid>). That string could be pasted into Claude/ChatGPT connectors but not into the CLI, which forced users to learn a second transport URL for the same bearer capability. `--remote` (start, openclaw, browser CLI) and the MCP `set_remote` tool now accept it, deriving the relay target deterministically through the single shared normalizer `parseRemoteTarget`: https://host[/prefix]/mcp/<uuid> -> wss://host[/prefix] + <uuid> http://<loopback>[/prefix]/mcp/<uuid> -> ws://<loopback>[/prefix] + <uuid> Bare UUID and ws(s) relay URL forms are unchanged. All #136 hardening is preserved: valid UUID only, no credentials/query/ fragment, no non-loopback plaintext relay transport, and no bearer value in errors, logs, help text, or CLI output. Generic HTTP(S) URLs without the exact /mcp/<uuid> suffix are rejected. Tests: connector normalization matrix (self-hosted path prefixes, ports, loopback forms), malformed/hostile URL rejections with leak assertions, a live set_remote connect over the connector form, a browser-CLI status run through an http connector URL, and a packaged-CLI help gate. Refs #145, #130 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…147) * feat: accept the HTTPS /mcp/<uuid> connector URL in --remote (#145) Users are shown one canonical connector credential in the extension (https://relay.api.vibebrowser.app/mcp/<uuid>). That string could be pasted into Claude/ChatGPT connectors but not into the CLI, which forced users to learn a second transport URL for the same bearer capability. `--remote` (start, openclaw, browser CLI) and the MCP `set_remote` tool now accept it, deriving the relay target deterministically through the single shared normalizer `parseRemoteTarget`: https://host[/prefix]/mcp/<uuid> -> wss://host[/prefix] + <uuid> http://<loopback>[/prefix]/mcp/<uuid> -> ws://<loopback>[/prefix] + <uuid> Bare UUID and ws(s) relay URL forms are unchanged. All #136 hardening is preserved: valid UUID only, no credentials/query/ fragment, no non-loopback plaintext relay transport, and no bearer value in errors, logs, help text, or CLI output. Generic HTTP(S) URLs without the exact /mcp/<uuid> suffix are rejected. Tests: connector normalization matrix (self-hosted path prefixes, ports, loopback forms), malformed/hostile URL rejections with leak assertions, a live set_remote connect over the connector form, a browser-CLI status run through an http connector URL, and a packaged-CLI help gate. Refs #145, #130 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore(release): bump @vibebrowser/mcp to 0.3.4 and @vibebrowser/cli to 0.3.2 npm already serves @vibebrowser/mcp@0.3.3 and @vibebrowser/cli@0.3.1, so merging #146 as-is would be a no-op for the publish workflow. Bump both packages and sync every mirrored version reference the plugin-bundle contract test asserts against package.json (server.json, mcpb/manifest.json, plugin.json, .mcp.json pin, marketplace.json). package-lock.json was regenerated via `npm version --no-git-tag-version`; no dependency changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(remote): redact every UUID path segment from remote targets A malformed-but-parseable connector URL such as https://host/mcp/<u1>/mcp/<u2> parses to relay base wss://host/mcp/<u1> and uuid <u2>. redactRemoteTarget only masked the full target and the final path segment, so <u1> leaked through any message that echoed the derived relay base. Redact every UUID-shaped path segment (raw and percent-decoded), while preserving full-target redaction, verbatim final-segment redaction and case-insensitive matching. Adds deterministic e2e-remote-lifecycle regressions for double-/mcp/ redaction, loopback-bypass hostnames rejecting plaintext, numeric loopback canonicalization, and encoded/path-confusion accept/reject outcomes. All UUIDs used are synthetic. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Summary
set_remoteoutputVerification
npm run buildnpx tsc --noEmitnpm run test:e2e:remote-lifecyclenpm testFixes #135
Parent: #130