feat(miner-ui): require a same-origin session cookie on the local API#5605
Conversation
Adds vite-auth.ts: a random per-process token delivered as an HttpOnly SameSite=Strict cookie, required on every /api/* request. Replaces the previous inconsistent/implicit loopback-IP trust (only one of the three API plugins even checked the caller's address) with real authentication that needs no client-side fetch changes.
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
|
Caution 🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥🟥 🛑 Gittensory review result - fixes requiredReview updated: 2026-07-13 09:13:54 UTC
🛑 Suggested Action - Manual Review Review summary Blockers
Nits — 7 non-blocking
CI checks failing
Review context
Contributor next steps
Signal definitions
[BETA] Chat with GittensoryAsk Gittensory a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands Visual preview
Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
Set-Cookie was applied unconditionally before the auth check, so an unauthenticated /api/* request could read the valid token straight off its own 401 response and replay it -- defeating the whole mechanism. Reject first, then only stamp the cookie on a response the caller is already authorized to receive (an authenticated /api/* request, or any non-/api/* page/asset load).
|
Fixed in 01c0ad5. Added a regression test asserting The |
Summary
apps/gittensory-miner-ui/vite-auth.ts: a random token generated once per dev-server process, delivered to the browser as anHttpOnly; SameSite=Strictcookie on every response, and required on every/api/*request. An unauthenticated request gets401.vite.config.ts, ahead ofrunStateApiPlugin/portfolioQueueApiPlugin/ledgersApiPlugin— an unauthenticated/api/*request is rejected before any of their middlewares run, so any future/api/*endpoint (e.g. a write action) is covered automatically with no per-endpoint wiring./) already carries the cookie on every subsequent same-originfetch()call.README.md.Why a cookie instead of a header/query token
The previous state was undocumented, implicit, and inconsistent:
vite-run-state-api.tshad its ownisLoopbackAddresscheck, butvite-portfolio-queue-api.tsandvite-ledgers-api.tshad no gate at all. Loopback-IP checking also isn't real authentication — it doesn't stop another local process, or a malicious page open in the same browser, from hitting the API.HttpOnlykeeps the token unreachable from any XSS in the SPA itself.SameSite=Strictmeans a cross-origin page — including a DNS-rebinding attempt, which resolves an attacker-controlled hostname to127.0.0.1rather than reusing this dev server's own origin — never has the cookie attached automatically by the browser. This satisfies the issue's literal acceptance criterion (an unauthenticated request is rejected) without touching the three existing read-only API files or any client fetcher.Closes #4858
Test plan
npm --workspace @loopover/ui-miner run typecheck(vianpm run ui:typecheck, which builds@loopover/ui-kitfirst)npm --workspace @loopover/ui-miner run lint— 0 errors (5 pre-existing, unrelated warnings)npm --workspace @loopover/ui-miner run test— 72/72 passing (15 new insrc/auth.test.ts, covering cookie parsing edge cases, the 401/fall-through decision, and the actual Vite middleware wiring for bothconfigureServerandconfigurePreviewServer)npm --workspace @loopover/ui-miner run buildGET /api/portfolio-queuereturns401with the documented error body; loading/captures theSet-Cookie; replaying that cookie onGET /api/portfolio-queuereturns200with the real summary payload.This change lives entirely under
apps/gittensory-miner-ui/**, whichvitest.config.ts's rootcoverage.includeexplicitly excludes (apps/**) — Codecov's patch gate does not apply here, matching the precedent set by #5479 (the PR this issue was blocked on).