Problem
When accessing wolfpack cross-origin through tailscale serve (e.g. browser on sgt making API calls to oldsgt), REST API calls (/api/sessions, /api/info, /api/ralph) fail with CORS errors:
Access to fetch at 'https://oldsgt.tail03f8e8.ts.net/api/ralph' from origin 'https://sgt.tail03f8e8.ts.net'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
WebSocket connections work fine (WS is exempt from CORS), so the terminal connects to the right session — but the missing REST metadata causes stale/wrong session content to display when switching sessions.
Root cause
Tailscale serve proxies https://hostname → http://127.0.0.1:PORT and strips the Origin header in transit. Our CORS logic (src/server/index.ts:107-119) checks req.headers.origin — when it's missing, CORS headers are skipped entirely, so the browser blocks the response.
Why it only affects cross-machine access
- Same-origin (browser on
oldsgt, requests to oldsgt): no CORS needed, works fine.
- Cross-origin (browser on
sgt, requests to oldsgt): CORS required, tailscale strips Origin, headers missing, browser blocks response.
Proposed fix
Detect requests that came through tailscale serve via the Tailscale-User-Login header. Tailscale serve injects authenticated Tailscale-User-* headers (stripped from client input, set by the local daemon — cannot be spoofed). When this header is present and Origin is missing, set Access-Control-Allow-Origin for the configured tailnet suffix.
if (!origin && TAILNET_SUFFIX && req.headers["tailscale-user-login"]) {
// Request came through tailscale serve — safe to allow tailnet CORS
}
Problem
When accessing wolfpack cross-origin through tailscale serve (e.g. browser on
sgtmaking API calls tooldsgt), REST API calls (/api/sessions,/api/info,/api/ralph) fail with CORS errors:WebSocket connections work fine (WS is exempt from CORS), so the terminal connects to the right session — but the missing REST metadata causes stale/wrong session content to display when switching sessions.
Root cause
Tailscale serve proxies
https://hostname→http://127.0.0.1:PORTand strips theOriginheader in transit. Our CORS logic (src/server/index.ts:107-119) checksreq.headers.origin— when it's missing, CORS headers are skipped entirely, so the browser blocks the response.Why it only affects cross-machine access
oldsgt, requests tooldsgt): no CORS needed, works fine.sgt, requests tooldsgt): CORS required, tailscale strips Origin, headers missing, browser blocks response.Proposed fix
Detect requests that came through tailscale serve via the
Tailscale-User-Loginheader. Tailscale serve injects authenticatedTailscale-User-*headers (stripped from client input, set by the local daemon — cannot be spoofed). When this header is present andOriginis missing, setAccess-Control-Allow-Originfor the configured tailnet suffix.