Skip to content

Self-host 2.0.0-beta.10: dashboard batch requests return 403 behind an HTTPS reverse proxy #2199

Description

@MylesMCook

Environment

  • ghcr.io/usefulsoftwareco/executor-selfhost:beta (2.0.0-beta.10), Docker, published on 127.0.0.1:4400
  • TLS terminated by a reverse proxy in front of the container
  • BETTER_AUTH_URL=https://executor.example.com

Symptom

Dashboard cards (for example Tools and Skills on an app's overview) show "Unable to complete this request", and the header shows "Could not reach the server". A full page reload renders the page; client-side navigation fails again, and the Retry button does not always recover. MCP is unaffected.

Cause

The dashboard sends its reads as POST /api/dashboard/batch. sameOrigin in packages/dashboard-start/src/implementation/batch-host.ts requires request.headers.origin === url.origin, where url comes from HttpServerRequest.toURL(request). Inside the container the request is always plain HTTP, so the derived origin is http://<host> while the browser sends Origin: https://<host>. The front proxy in apps/hosted/self-host/native/main.go uses ReverseProxy.Rewrite without SetXForwarded, so an X-Forwarded-Proto header from the outer proxy does not reach the server either. The result is an empty 403.

Reproduce (no sign-in needed)

curl -s -o /dev/null -w '%{http_code}\n' -X POST https://executor.example.com/api/dashboard/batch \
  -H 'content-type: application/json' -H 'origin: https://executor.example.com' -d '{}'
# 403

curl -s -o /dev/null -w '%{http_code}\n' -X POST https://executor.example.com/api/dashboard/batch \
  -H 'content-type: application/json' -H 'origin: http://executor.example.com' -d '{}'
# 400 (passes the origin check, rejects the empty body)

The same happens directly against 127.0.0.1:4400 with a Host header for the public name, with or without X-Forwarded-Proto: https.

Suggested fix

Compare the Origin header against the configured BETTER_AUTH_URL origin instead of the origin derived from the in-container request, or forward and honor X-Forwarded-Proto.

Workaround

Rewrite Origin from https://<host> to http://<host> at the outer proxy, only for POST /api/dashboard/batch and only when it already equals the instance's own HTTPS origin.

Related

The built-in Executor management app has the setup-time origin written into its source: executorAppSource(origin, ...) in apps/hosted/server/src/implementation/executor-app.ts sets source.url, allowedOrigin and baseUrl. After BETTER_AUTH_URL changes, the app keeps fetching <old origin>/openapi.json and cannot load its tools until it is removed and added again from the catalog.

Activity

  1. joshuajbrunner commented on Oct 9, 2026

    @joshuajbrunner

    Same issue here, latest beta

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions