fix: centralize public origin checks for proxied dashboards (#5278)

Centralizes browser-mutation origin validation into `src/server/origin/publicOrigin.ts` and wires it through the authz pipeline, replacing the per-route same-origin-only check that 403'd dashboard mutations when served behind a reverse proxy on a different public origin. The new module resolves the allowed public origin from configured base-URL env vars or trusted forwarded headers (only when OMNIROUTE_TRUST_PROXY is set AND the peer is loopback/LAN via peer-stamp), validates Sec-Fetch-Site metadata, and sanitizes Host/Forwarded inputs (rejects control chars, userinfo, path/query in Host).

Reviewed sound; validated locally: authz/public-origin + pipeline suites 27/27 green (incl. invalid-origin reject + configured-origin accept), typecheck clean. Maintainer fix-up: moved the new test from tests/unit/server/ (not collected by any runner — orphan-test gate fail) into tests/unit/authz/. Remaining red CI shards are the pre-existing #4076 Dockerfile heap base-red on `main` (unrelated; de-brittled in the v3.8.40 release line).

Co-authored-by: Thinkscape <Thinkscape@users.noreply.github.com>
This commit is contained in:
Arthur Bodera
2026-06-29 14:43:14 +10:00
committed by GitHub
parent bc9d18457d
commit 1c18be4f8f
11 changed files with 600 additions and 40 deletions

View File

@@ -113,12 +113,16 @@ NODE_ENV=production
HOSTNAME=0.0.0.0
DATA_DIR=/app/data
APP_LOG_TO_FILE=true
AUTH_COOKIE_SECURE=false
AUTH_COOKIE_SECURE=true
REQUIRE_API_KEY=false
# === Domain (change to your domain) ===
BASE_URL=https://llms.seudominio.com
# === URLs (change to your domain) ===
# Internal server-to-server base URL for scheduled jobs / self-fetches.
BASE_URL=http://127.0.0.1:20128
# Browser-facing URL used for OAuth callbacks, dashboard links, and same-origin checks.
NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
# Optional explicit public origin override for generated public asset URLs.
# OMNIROUTE_PUBLIC_BASE_URL=https://llms.seudominio.com
# === Cloud Sync (optional) ===
# CLOUD_URL=https://cloud.omniroute.online
@@ -207,6 +211,7 @@ server {
location / {
proxy_pass http://127.0.0.1:20128;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
@@ -238,6 +243,12 @@ Keep reverse-proxy stream timeouts aligned with your OmniRoute timeout env vars.
`FETCH_TIMEOUT_MS` / `STREAM_IDLE_TIMEOUT_MS`, raise `proxy_read_timeout` / `proxy_send_timeout`
above the same threshold.
OmniRoute uses `NEXT_PUBLIC_BASE_URL` as the canonical browser-facing origin for OAuth,
public links, and dashboard mutation origin checks. The `X-Forwarded-*` headers above are
still useful routing metadata, but they are not a replacement for setting the explicit public
URL. Only enable `OMNIROUTE_TRUST_PROXY` if OmniRoute is not directly reachable by clients and
your proxy strips/rebuilds incoming forwarded headers.
### 3.3 Enable and Test
```bash