mirror of https://github.com/garrytan/gstack.git
Activity stream and inspector events SSE endpoints accepted the root
AUTH_TOKEN via `?token=` query param (EventSource can't send Authorization
headers). URLs leak to browser history, referer headers, server logs,
crash reports, and refactoring accidents. Codex flagged this during the
/plan-ceo-review outside voice pass.
New auth model: the extension calls POST /sse-session with a Bearer token
and receives a view-only session cookie (HttpOnly, SameSite=Strict, 30-min
TTL). EventSource is opened with `withCredentials: true` so the browser
sends the cookie back on the SSE connection. The ?token= query param is
GONE — no more URL-borne secrets.
Scope isolation (prior learning cookie-picker-auth-isolation, 10/10
confidence): the SSE session cookie grants access to /activity/stream and
/inspector/events ONLY. The token is never valid against /command, /token,
or any mutating endpoint. A leaked cookie can watch activity; it cannot
execute browser commands.
Components
* browse/src/sse-session-cookie.ts — registry: mint/validate/extract/
build-cookie. 256-bit tokens, 30-min TTL, lazy expiry pruning,
no imports from token-registry (scope isolation enforced by module
boundary).
* browse/src/server.ts — POST /sse-session mint endpoint (requires
Bearer). /activity/stream and /inspector/events now accept Bearer
OR the session cookie, and reject ?token= query param.
* extension/sidepanel.js — ensureSseSessionCookie() bootstrap call,
EventSource opened with withCredentials:true on both SSE endpoints.
Tested via the source guards; behavioral test is the E2E pairing
flow that lands later in the wave.
* browse/test/sse-session-cookie.test.ts — 20 unit tests covering
mint entropy, TTL enforcement, cookie flag invariants, cookie
parsing from multi-cookie headers, and scope-isolation contract
guard (module must not import token-registry).
* browse/test/server-auth.test.ts — existing /activity/stream auth
test updated to assert the new cookie-based gate and the absence
of the ?token= query param.
Cookie flag choices:
* HttpOnly: token not readable from page JS (mitigates XSS
exfiltration).
* SameSite=Strict: cookie not sent on cross-site requests (mitigates
CSRF). Fine for SSE because the extension connects to 127.0.0.1
directly.
* Path=/: cookie scoped to the whole origin.
* Max-Age=1800: 30 minutes, matches TTL. Extension re-mints on
reconnect when daemon restarts.
* Secure NOT set: daemon binds to 127.0.0.1 over plain HTTP. Adding
Secure would block the browser from ever sending the cookie back.
Add Secure when gstack ships over HTTPS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .. | ||
| fixtures | ||
| activity.test.ts | ||
| adversarial-security.test.ts | ||
| batch.test.ts | ||
| browser-manager-unit.test.ts | ||
| build.test.ts | ||
| bun-polyfill.test.ts | ||
| commands.test.ts | ||
| compare-board.test.ts | ||
| config.test.ts | ||
| content-security.test.ts | ||
| cookie-import-browser.test.ts | ||
| cookie-picker-routes.test.ts | ||
| data-platform.test.ts | ||
| dual-listener.test.ts | ||
| dx-polish.test.ts | ||
| error-handling.test.ts | ||
| file-drop.test.ts | ||
| find-browse.test.ts | ||
| findport.test.ts | ||
| from-file-path-validation.test.ts | ||
| gstack-config.test.ts | ||
| gstack-update-check.test.ts | ||
| handoff.test.ts | ||
| learnings-injection.test.ts | ||
| path-validation.test.ts | ||
| pdf-flags.test.ts | ||
| platform.test.ts | ||
| security-adversarial-fixes.test.ts | ||
| security-adversarial.test.ts | ||
| security-audit-r2.test.ts | ||
| security-bench.test.ts | ||
| security-bunnative.test.ts | ||
| security-classifier.test.ts | ||
| security-e2e-fullstack.test.ts | ||
| security-integration.test.ts | ||
| security-live-playwright.test.ts | ||
| security-review-flow.test.ts | ||
| security-review-fullstack.test.ts | ||
| security-review-sidepanel-e2e.test.ts | ||
| security-sidepanel-dom.test.ts | ||
| security-source-contracts.test.ts | ||
| security.test.ts | ||
| server-auth.test.ts | ||
| sidebar-agent-roundtrip.test.ts | ||
| sidebar-agent.test.ts | ||
| sidebar-integration.test.ts | ||
| sidebar-security.test.ts | ||
| sidebar-unit.test.ts | ||
| sidebar-ux.test.ts | ||
| snapshot.test.ts | ||
| sse-session-cookie.test.ts | ||
| state-ttl.test.ts | ||
| tab-isolation.test.ts | ||
| test-server.ts | ||
| token-registry.test.ts | ||
| url-validation.test.ts | ||
| watch.test.ts | ||
| watchdog.test.ts | ||
| welcome-page.test.ts | ||