Skip to content

fix: allow configured browser origins through reverse proxies - #880

Open
chbndrhnns wants to merge 4 commits into
pascalorg:mainfrom
chbndrhnns:fix/proxy-scene-api-auth
Open

chbndrhnns wants to merge 4 commits into
pascalorg:mainfrom
chbndrhnns:fix/proxy-scene-api-auth

Conversation

@chbndrhnns

@chbndrhnns chbndrhnns commented Sep 16, 2026 •

Copy link
Copy Markdown

Browser scene creation returns 503 on reverse-proxied self-hosted editor

Reproduction

  1. Deploy Pascal Editor behind a reverse proxy at https://pascal.example.com.
  2. Set PASCAL_SCENE_API_ORIGINS=https://pascal.example.com.
  3. Leave PASCAL_SCENE_API_TOKEN unset.
  4. Open /scenes and click Create new scene.

The browser POST to /api/scenes fails with:

{"error":"scene_api_token_required"}

The UI displays Failed to create scene (503).

Root cause

scene-api-security.ts correctly validates the configured browser origin, but validateAuth() then requires a token for every non-loopback request. A same-origin browser request arriving through the reverse proxy is not identified as loopback. The frontend does not send Authorization or X-Pascal-Scene-Token, so scene creation cannot work with the documented public-origin configuration.

Expected behavior

A browser request from an origin listed in PASCAL_SCENE_API_ORIGINS should be accepted without an API token, while non-browser/API clients should continue to require token authentication.

Environment

  • Pascal Editor deployed with Docker/Openship
  • Public origin configured with PASCAL_SCENE_API_ORIGINS
  • Reverse proxy terminates TLS

Note

Medium Risk
Relaxes no-token auth for same-origin browser calls based on Origin plus forwarded headers; misconfigured proxies that trust client-supplied X-Forwarded-* could widen who bypasses token checks.

Overview
Fixes scene creation 503 when the editor runs behind a reverse proxy with only PASCAL_SCENE_API_ORIGINS set and no API token.

validateAuth now treats loopback and same-origin browser traffic as allowed when no PASCAL_SCENE_API_TOKEN is set, but only if the request Origin is listed in PASCAL_SCENE_API_ORIGINS. If a token is configured, proxy-shaped same-origin requests still need bearer/x-pascal-scene-token auth.

isSameOrigin no longer compares against the internal request.url; it reconstructs the public URL from the first hop in x-forwarded-host / x-forwarded-proto (including comma-chained values) and falls back safely when those headers are malformed.

New tests cover proxied same-origin success, chained forwarded headers, malformed forwards, and strict token enforcement when a secret is set.

Reviewed by Cursor Bugbot for commit 9e7bad6. Bugbot is set up for automated code reviews on this repo. Configure here.

@pascal

pascal Bot commented Sep 16, 2026

Copy link
Copy Markdown

I hit an error while handling your request (Model unavailable on AI Gateway free tier: Free tier users do not have access to this model. Upgrade to paid credits at https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai%3Fmodal%3Dtop-up for unrestricted…).

Please try again, rephrase, or reach out if it keeps failing.

Error id: 5fd6ce60-1278-45c6-9c6c-9d3c5be88917

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread apps/editor/lib/scene-api-security.ts Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 432381e. Configure here.

Comment thread apps/editor/lib/scene-api-security.ts Outdated
Comment thread apps/editor/lib/scene-api-security.ts Outdated
const forwardedProto = request.headers.get('x-forwarded-proto')
const requestUrl = forwardedHost
? new URL(`${forwardedProto ?? 'https'}://${forwardedHost.split(',')[0]?.trim()}`)
: new URL(request.url)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proto ignored without forwarded host

Medium Severity

isSameOrigin only applies x-forwarded-proto when x-forwarded-host is also present, and it never falls back to Host the way resolveBaseUrl does. TLS-terminating proxies often set Host and x-forwarded-proto without x-forwarded-host, so the comparison keeps the internal http URL and the new same-origin auth bypass still fails with scene_api_token_required.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 432381e. Configure here.

@dkbbdev

dkbbdev commented Sep 17, 2026

Copy link
Copy Markdown

Verified this patch on a self-hosted deployment behind a Cloudflare Tunnel (no token, host is not loopback):

  • Before: every /api/scenes call from the browser returned 503 {"error":"scene_api_token_required"} — the app was unusable behind the proxy (issue Browser scene creation returns 503 behind reverse proxy #878).
  • After: with PASCAL_SCENE_API_ORIGINS=https://<host> set (and no PASCAL_SCENE_API_TOKEN), same-origin browser requests pass auth: scene list returns 200 and scene creation returns 201, verified end-to-end through the tunnel from an external network.

One deployment note from testing: both the http:// and https:// origin variants may be needed while a zone's cert is still provisioning, since browsers on plain http send the http origin. Might be worth a line in the README/env example.

Thanks for the fix — it unblocked our deployment.

This branch has not been deployed

No deployments
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.

2 participants