The Altinity SQL Browser is a single self-contained HTML file (no application
backend) served from a ClickHouse cluster's user_files/ by an
<http_handlers> static rule. It talks only to that ClickHouse server and your
OAuth IdP, and makes zero third-party requests. The notes below describe how to
report a vulnerability and the threat model you should deploy against.
Please do not open a public GitHub issue for a security vulnerability.
Report privately, either way:
- GitHub private advisory (preferred): on this repository, go to Security → Advisories → Report a vulnerability. This opens a private thread with the maintainers.
- Email:
security@altinity.com. Please include "altinity-sql-browser" in the subject and enough detail to reproduce (affected version/commit — see the build stamp in the user menu, deploy shape, and steps).
We aim to acknowledge a report within a few business days and to keep you updated as we triage and fix. Please give us a reasonable window to ship a fix before any public disclosure; we're happy to credit reporters who want it.
The app loads its OAuth configuration from config.json (served as
/sql/config.json), which is delivered to the browser. Anything in it is
readable by any user who can reach the page. Never put a value in config.json
that you would not publish.
- Prefer a PKCE public client (no secret). Register a "SPA / public /
native" client; the PKCE
code_verifierauthenticates the token exchange, so noclient_secretis needed andconfig.jsonstays secret-free. This is the recommended shape and what the supporteddeploy/install.shrenders — it never writes aclient_secret, so a standard install is secret-free by construction. - If your IdP requires a
client_secreton the in-browser token exchange (e.g. a Google "Web application" client), the code accepts it inconfig.json, but because the file ships to browsers you must treat it as public: lock the redirect URI to exactlyhttps://<host>/sqlwith the IdP and use a suitably scoped consent screen, so a leaked secret can't be replayed to a different redirect. A secret only entersconfig.jsonthrough a hand-authored config (e.g. an inline<http_handlers>rule) — apply this rule wherever you do that. - Or front the app with a broker. An OIDC broker / auth proxy holds the
provider secret and exposes a public PKCE client; the browser talks only to
the broker and
config.jsoncarries no secret.
This mirrors the project's contributor rule (CLAUDE.md hard rule 3) and the
README's "Configuring OAuth" section.
OAuth tokens (id / access / refresh) and the PKCE state/verifier used during
the redirect round-trip are kept in sessionStorage: scoped to the browser
tab and cleared when the tab closes. Tokens are never written to
localStorage or cookies. There is no server-side session.
deploy/http_handlers.xml serves the SPA with a strict
Content-Security-Policy plus X-Content-Type-Options: nosniff and
Referrer-Policy: no-referrer. The CSP is default-src 'none' with everything
re-allowed explicitly; the load-bearing directive is:
connect-src 'self' <issuer-origins>— bounds where the page may send data, so an injected script cannot exfiltrate thesessionStoragetokens to an attacker-controlled host.'self'covers ClickHouse queries +config.json; the issuer origins cover OIDC discovery and the token endpoint.deploy/install.shfills this list automatically from your issuer's OIDC discovery document (for a manual non-Google install, edit theconnect-srcline indeploy/http_handlers.xml).frame-ancestors 'none'(anti-clickjacking),base-uri 'none',img-src data:, and asandbox=""(script-less, inert)srcdociframe for the result cell-detail HTML preview.
If you deploy the SPA without this handler, you lose these protections — ship the provided CSP/headers (or equivalents).
The SPA is a client. The following are configured and secured by whoever deploys it, not by this project:
- ClickHouse access control — what a signed-in user can read/run is governed
by ClickHouse RBAC / grants and the
<token_processor>JWT validation, not by the browser. The UI cannot grant access the server doesn't already allow. - IdP configuration — client type, redirect-URI allowlist, consent scopes.
- TLS termination — always serve the page and the ClickHouse endpoint over HTTPS.