fix(bridge): gate /api/config like every other endpoint - #38
Merged
Conversation
There is no global gate — each route calls checkAccess/guard itself — and /api/config returned before doing so. It was the one endpoint that bypassed the same-origin check and the COLLIE_PUBLIC_HOSTS allowlist. Low severity: it exposes the VAPID public key (public by design) and the build id, and with no CORS headers a browser can't read the response cross-origin anyway. But the host allowlist exists for DNS rebinding, where the attacker's page *becomes* same-origin, and this route skipped it. No client impact. The PWA calls it same-origin, read level doesn't require the device header, and ConnectionBanner short-circuits to AuthErrorBanner before its red-state probe runs, so a refusal can't surface as "bridge unreachable". Noted in passing by @Optic00 in #32; the rest of that issue is a separate design question.
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.
/api/configreturned before callingguard(). There is no global gate in the bridge — every routecalls
checkAccess/guarditself — so this was the one endpoint that bypassed both the same-origincheck and the
COLLIE_PUBLIC_HOSTSallowlist.Reproduced against a live 0.16.0 bridge, with a gated endpoint as the control:
Severity is low. What it exposes is the VAPID public key — handed to every browser by design —
and the build id. The bridge sends no CORS headers, so cross-origin JS can't read the response
anyway. The reason to close it is that
COLLIE_PUBLIC_HOSTSexists specifically for DNS rebinding,where the attacker's page becomes same-origin and the browser's own SOP stops helping. Every other
route is covered; this one wasn't.
No client impact, checked rather than assumed:
api.fetchConfig,web/src/lib/api.ts:304).ConnectionBannershort-circuits to
AuthErrorBanneron a 401/403 before the probe runs(
web/src/components/connection-banner.tsx:46), so a refusal here can't surface as"bridge unreachable".
The route lives inside
Bun.serve, which stays unit-untested per CLAUDE.md, so verification is thelive probe above plus its negative control — re-run post-deploy on 0.16.1.
Noted in passing by @Optic00 in #32. This does not close #32 — the substance of that issue is the
bridge-wide blast radius of snooze/prefs, which is a design decision still open.
🤖 Generated with Claude Code