Skip to content

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

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

chbndrhnns wants to merge 3 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

High Risk
Changes scene API authentication rules behind reverse proxies; mis-trusted forwarded headers or same-origin logic could weaken token requirements for non-browser clients.

Overview
Fixes 503 scene_api_token_required when the editor sits behind a reverse proxy and PASCAL_SCENE_API_ORIGINS is set without an API token.

validateAuth now skips token checks only when the request Origin is in the configured allowlist and isSameOrigin agrees—so a spoofed Origin alone cannot bypass auth when a token is configured. isSameOrigin reconstructs the public URL from the first x-forwarded-host / x-forwarded-proto values (including chained proxy lists), with safe fallback when those headers are malformed.

New tests cover proxied same-origin success, multi-hop forwarded headers, bad forwarded values, and token-required behavior when only Origin is forged.

Reviewed by Cursor Bugbot for commit 634995b. 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

@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.

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.

1 participant