fix(remote-access): same-origin PTY WS upgrade + trusted-proxy-gated X-Forwarded-* trust#318
Merged
Merged
Conversation
…X-Forwarded-* trust The PTY WebSocket origin gate was a static localhost-only allowlist, so any non-localhost access (Tailscale IP, LAN IP, a domain) got 403 upgrade.origin_rejected on the workspace terminal — while the HTTP CSRF check already did dynamic same-origin comparison. Community-reported against the documented Docker/LAN self-hosting path. - workspaces-ws: accept same-origin upgrades (Origin host == Host header), mirroring the HTTP middleware; static allowlist + WEB_TERMINAL_ALLOWED_ORIGINS remain for cross-origin topologies. Unit-specced. - routes/auth: honor X-Forwarded-Proto / X-Forwarded-For only when the socket peer is a configured trusted proxy (previously trusted unconditionally, contradicting the code comment and playbook 03 — an attacker could coerce a Secure cookie over plain HTTP). Wired trustedProxies from WebPlugin. - README: new "Remote access" section (Tailscale/LAN direct, reverse proxy recipe with nginx headers, public-internet caveats, cross-origin env vars). - playbook 07 updated to the new origin contract. Verified end-to-end: bound 0.0.0.0, logged in and attached a live workspace PTY via LAN IP origin (same code path as Tailscale); cross-origin upgrade still 403s. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Merged
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
upgrade.origin_rejected): the PTY WebSocket origin gate was a static localhost-only allowlist; now it accepts same-origin upgrades (Origin host == Host header), mirroring the HTTP middleware's CSRF rule. Any direct bind — LAN IP, Tailscale IP, domain — works with zero config; cross-origin still 403s.OPENALICE_TRUSTED_PROXIES). Previously trusted unconditionally, contradicting the in-code comment and playbook 03 — any client could coerce aSecurecookie over plain HTTP and break login.WEB_TERMINAL_ALLOWED_ORIGINS,OPENALICE_CSRF_TRUSTED_ORIGINS).Test plan
npx tsc --noEmitcleanpnpm testpasses (113 files / 1820 tests, incl. newworkspaces-ws.spec.ts+routes/auth.spec.ts)0.0.0.0, browser via LAN IP192.168.31.49:47331→ admin-token login → resumed a paused workspace session → WS upgrade accepted, received{"type":"attached",pid:…}from the live claude PTYOrigin: http://evil.example.comupgrade →403+upgrade.origin_rejectedlogBoundary touch
Auth boundary: WS origin gate semantics (same-origin acceptance — browser Origin is not forgeable from a foreign page, so this admits exactly pages Alice served itself) and forwarded-header trust (strictly narrowed, never widened).
🤖 Generated with Claude Code