What happened
Using the "Advanced — connect to another server" field on sql.demo.altinity.cloud
to connect to a ClickHouse host outside the deployment's connectSrc allowlist
fails with a generic browser "Failed to fetch" — no indication that the request
never left the page.
Root cause
connect-src (CSP, helm/altinity-sql-browser/values.yaml:36-39, rendered via
deploy/caddy/Caddyfile:50) is a fixed origin allowlist by design (see
README.md:699-720, docs/DEPLOYMENT.md, docs/LOGIN-SCREEN.md:159-161). The
"Advanced" host field (net/oauth-config.ts, basic-auth custom host) lets a
user type any host:port, but the browser silently refuses the fetch unless
that origin is in connect-src. Confirmed via DevTools console:
Connecting to '<host>' violates the following Content Security Policy directive:
"connect-src 'self' <allowlisted origins>". The action has been blocked.
Fetch API cannot load <host>. Refused to connect because it violates the
document's Content Security Policy.
The app's error handling has no visibility into why the fetch rejected —
ch-client.ts's authedFetch catch block treats any rejected fetch() the
same way (ctx.onTransportOffline), so a CSP block, a DNS failure, and a
dropped TCP connection all render identically to the user.
Suggested fix
Detect a CSP-blocked connect attempt and surface a specific message (e.g. "this
server isn't in this deployment's connect-src allowlist — ask an admin to add
https://<host> to connectSrc") instead of the generic transport-offline
message. A SecurityPolicyViolationEvent listener (document.addEventListener ('securitypolicyviolation', ...)) filtered to violatedDirective === 'connect-src' firing around the same time as the failed fetch would let the UI
distinguish this case from real network failures.
Why filed as inbox / deferred
Found while investigating an unrelated live-connectivity report (a user hitting
this exact wall against a customer production cluster via sql.demo.altinity.cloud).
Out of scope for that investigation; the immediate fix there was overriding
connectSrc in deploy/helm/values-demo.yaml (see CHANGELOG [Unreleased]).
This issue is the UX/error-surfacing follow-up.
What happened
Using the "Advanced — connect to another server" field on
sql.demo.altinity.cloudto connect to a ClickHouse host outside the deployment's
connectSrcallowlistfails with a generic browser "Failed to fetch" — no indication that the request
never left the page.
Root cause
connect-src(CSP,helm/altinity-sql-browser/values.yaml:36-39, rendered viadeploy/caddy/Caddyfile:50) is a fixed origin allowlist by design (seeREADME.md:699-720, docs/DEPLOYMENT.md, docs/LOGIN-SCREEN.md:159-161). The
"Advanced" host field (
net/oauth-config.ts, basic-auth custom host) lets auser type any host:port, but the browser silently refuses the fetch unless
that origin is in
connect-src. Confirmed via DevTools console:The app's error handling has no visibility into why the fetch rejected —
ch-client.ts'sauthedFetchcatch block treats any rejectedfetch()thesame way (
ctx.onTransportOffline), so a CSP block, a DNS failure, and adropped TCP connection all render identically to the user.
Suggested fix
Detect a CSP-blocked connect attempt and surface a specific message (e.g. "this
server isn't in this deployment's connect-src allowlist — ask an admin to add
https://<host>toconnectSrc") instead of the generic transport-offlinemessage. A
SecurityPolicyViolationEventlistener (document.addEventListener ('securitypolicyviolation', ...)) filtered toviolatedDirective === 'connect-src'firing around the same time as the failed fetch would let the UIdistinguish this case from real network failures.
Why filed as inbox / deferred
Found while investigating an unrelated live-connectivity report (a user hitting
this exact wall against a customer production cluster via
sql.demo.altinity.cloud).Out of scope for that investigation; the immediate fix there was overriding
connectSrcindeploy/helm/values-demo.yaml(see CHANGELOG[Unreleased]).This issue is the UX/error-surfacing follow-up.