Skip to content

[HYPER-11] fix: WebSocket origin checker rejects cross-origin connections when ALLOWED_ORIGINS is unset#30

Merged
aspiers merged 2 commits intomainfrom
wss-fix
Feb 11, 2026
Merged

[HYPER-11] fix: WebSocket origin checker rejects cross-origin connections when ALLOWED_ORIGINS is unset#30
aspiers merged 2 commits intomainfrom
wss-fix

Conversation

@aspiers
Copy link
Contributor

@aspiers aspiers commented Feb 11, 2026

Summary

  • Fix WebSocket 403 for cross-origin clients (e.g. impactindexer.org): When ALLOWED_ORIGINS is not configured, the CORS middleware allowed all origins but the WebSocket CheckOrigin rejected all cross-origin connections. Now both default to allow-all, matching pre-security-fix behavior. Closes [Security] WebSocket CheckOrigin accepts all origins (CSWSH risk) #3.
  • Document all 11 missing env vars in .env.example: ALLOWED_ORIGINS, TRUST_PROXY_HEADERS, DOMAIN_DID, LEXICON_DIR, JETSTREAM_URL, JETSTREAM_COLLECTIONS, BACKFILL_ON_START, BACKFILL_COLLECTIONS, BACKFILL_PDS_CONCURRENCY, BACKFILL_REPO_TIMEOUT, PLC_DIRECTORY_URL.

Root Cause

PR #19 (security fixes) tightened makeOriginChecker in subscription/handler.go to iterate over configured origins. When ALLOWED_ORIGINS is empty (the default), the list is nil, so the loop matches nothing and every cross-origin WebSocket upgrade gets 403 Forbidden.

The CORS middleware has the opposite default — empty origins means allow all (Access-Control-Allow-Origin: *). This inconsistency meant HTTP GraphQL queries worked from any origin but WebSocket subscriptions were silently blocked.

Testing

  • Added handler_test.go with table-driven tests covering: nil origins, empty origins, wildcard, matching, non-matching, and multi-origin scenarios.
  • Verified against hyperindex.test.certified.app: Origin: https://impactindexer.org returned 403 before the fix.

aspiers and others added 2 commits February 11, 2026 23:44
Without this patch, the WebSocket origin checker only allowed all origins
when ALLOWED_ORIGINS was explicitly set to "*". If ALLOWED_ORIGINS was
unset or empty, the checker would fall through to the restrictive logic
that rejects origins not in the (empty) allowlist.

This is a problem because it's inconsistent with the CORS middleware
behavior, which allows all origins when ALLOWED_ORIGINS is not configured.
Users expect WebSocket connections to work out of the box in development.

This patch solves the problem by treating empty/nil ALLOWED_ORIGINS the
same as "*" - allowing all origins. The logging now distinguishes between
"not configured" vs explicitly set to "*" for better observability.

Changes:
- Handle empty/nil ALLOWED_ORIGINS as permissive (allow all)
- Add distinct log messages for unconfigured vs wildcard cases
- Add comprehensive test coverage with 9 test cases

Co-authored-by: Claude Code <claude-code@noreply.anthropic.com>
11 config vars from config.go were undocumented:
ALLOWED_ORIGINS, TRUST_PROXY_HEADERS, DOMAIN_DID, LEXICON_DIR,
JETSTREAM_URL, JETSTREAM_COLLECTIONS, BACKFILL_ON_START,
BACKFILL_COLLECTIONS, BACKFILL_PDS_CONCURRENCY,
BACKFILL_REPO_TIMEOUT, PLC_DIRECTORY_URL
@vercel
Copy link

vercel bot commented Feb 11, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hyperindex Ready Ready Preview, Comment Feb 11, 2026 10:49am

Request Review

@railway-app
Copy link

railway-app bot commented Feb 11, 2026

🚅 Environment hyperindex-pr-30 in hypercerts has no services deployed.

@aspiers aspiers merged commit 9de3ef9 into main Feb 11, 2026
5 checks passed
@aspiers aspiers deleted the wss-fix branch February 11, 2026 11:02
@aspiers aspiers changed the title fix: WebSocket origin checker rejects cross-origin connections when ALLOWED_ORIGINS is unset [HYPER-11] fix: WebSocket origin checker rejects cross-origin connections when ALLOWED_ORIGINS is unset Feb 11, 2026
@linear
Copy link

linear bot commented Feb 11, 2026

HYPER-11 Fix Hyperindex

Seems to have stopped working

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security] WebSocket CheckOrigin accepts all origins (CSWSH risk)

1 participant