Repository navigation
fix(server): same-origin check on cookie WebSocket upgrades, Secure session cookie - #65
Merged
Merged
Conversation
…ession cookie Browsers attach the T3 session cookie to a WebSocket opened by any same-site page. On this box every app shares one IP (and later, sibling subdomains of one domain), so a page on another port could open /ws with the user's session. Cookie-authenticated upgrades now require the page's own origin (or the existing credentialed CORS allowlist); ticket, bearer and DPoP clients are unchanged. The session cookie is also marked Secure when the request arrived over HTTPS, and re-set on the session check so existing cookies pick it up without a re-pair. Cookies ignore ports, so without it the prod cookie was sent in cleartext to the plain-HTTP apps on the same IP. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Owner
Author
Test deployment (degraded / tunnel mode)This branch is running on a local test instance, but the external HTTPS # Open the tunnel from your laptop (keep this session open):
ssh -L 8080:127.0.0.1:3779 dgordon@<SERVER_IP>
# THEN, inside that SSH session (i.e. on <SERVER_IP>, not your laptop),
# mint a link whose URL points at your tunnel origin:
node scripts/test-status.ts --pair 7449 --base-url http://127.0.0.1:8080
# finally open the printed http://127.0.0.1:8080/pair#token=... in your local browserSlot: external 7449 ⇄ loopback 3779. |
Owner
Author
Test deployment (correction)The auto-posted comment above says "degraded mode". That came from a startup race: the external port answers fine. Test instance: https://15.204.108.12:7449 To get a pairing link (deliberately not posted here), run on the box: Checked through Caddy on this slot:
|
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.
Every app on this box shares one IP, and cookies are scoped by host, not port. That causes two problems:
/wshijack. A page on any other port (DanCode :8443, Abba Bank :9443, Alfred :6443, a test deploy, or later a sibling subdomain under gordonlabs.dev) can openwss://…:7443/ws, and the browser attaches the T3 session cookie. One XSS in any co-hosted app could take over T3, including its terminals.Secureflag, so the browser also sends it in plain text to the raw HTTP ports on the same IP (:3000, :3001, :4173, :8000, :8080).These are items H1 and H3 from the box security review. The plan is being tracked in the consolidated deployment-security thread.
Fix
authenticateWebSocketUpgradenow rejects a cookie-authenticated upgrade (one with nowsTicketand noAuthorizationheader) whoseOriginis not the page's own origin. The expected origin comes fromX-Forwarded-ProtoplusX-Forwarded-Host, falling back toHost; Caddy'sheader_up Host {host}drops the port, but the port is what separates the apps.T3CODE_DEV_ALLOWED_ORIGINS) still passes. Requests without anOriginheader (non-browser clients) are unaffected. The ticket, bearer and DPoP paths are unchanged, so mobile, desktop and app.t3.codes keep working.Securecookie over HTTPS. The session cookie is markedSecurewhenever the request arrived over HTTPS./api/auth/sessionre-sets it over HTTPS, so existing browser sessions pick up the flag without re-pairing.DESKTOP_RENDERER_ORIGINSmoved into the newauth/browserOrigin.ts, so CORS and the upgrade check share one list.Verification
vp test run src/auth/browserOrigin.test.ts src/auth/EnvironmentAuth.test.ts src/auth/http.test.ts: 24 tests pass. The new cases cover same port vs. another port, scheme mismatch, the default 443 port, sibling subdomains, the allowlist, a missingOrigin, and a ticket from another origin.tsc --noEmitonapps/serverreports no new errors (the existingexternalLauncher.test.tserrors are unrelated).Originis rejected with 401.🤖 Generated with Claude Code