Skip to content

Restrict embedded editor postMessage to allowed origins using IFRAME_ALLOWED_ORIGINS#1676

Open
jasoncoffman wants to merge 2 commits intopinterest:masterfrom
jasoncoffman:fix/cross-origin-postmessage
Open

Restrict embedded editor postMessage to allowed origins using IFRAME_ALLOWED_ORIGINS#1676
jasoncoffman wants to merge 2 commits intopinterest:masterfrom
jasoncoffman:fix/cross-origin-postmessage

Conversation

@jasoncoffman
Copy link
Contributor

@jasoncoffman jasoncoffman commented Mar 18, 2026

Problem

The EmbeddedQueryPage accepts postMessage calls from any origin and uses '*' as the target
for outgoing messages. This means any page — not just the intended embedding host — can inject
queries into the editor via SET_QUERY, potentially leading to unauthorized or unintended query
execution.

Solution

Validate event.origin against the existing IFRAME_ALLOWED_ORIGINS server configuration before
processing incoming SET_QUERY messages. This reuses the same setting that already controls CSP
frame-ancestors, so deployers get postMessage protection automatically with zero additional
configuration.

Changes

  • New API endpoint (GET /utils/embedded/allowed_origins/): Exposes IFRAME_ALLOWED_ORIGINS
    to the frontend. Requires authentication but not admin access.
  • Origin validation in EmbeddedQueryPage: Incoming messages are checked against the allowed
    list. Messages from unlisted origins are silently dropped. Messages coming from the Querybook origin are permitted.
  • No interim security gap: The message listener and SEND_QUERY handshake are deferred until
    the allowed origins have loaded, so there is no window where unvalidated messages are accepted.
  • Updated docs: infra_config.mdx now notes the dual role of IFRAME_ALLOWED_ORIGINS.

Backward compatibility

When IFRAME_ALLOWED_ORIGINS is not configured (the default), the allowed list is empty and all
origins are accepted — identical to the current behavior. No action is required from existing
deployers.

Alternatives considered

  1. Move allowed origins into querybook_public_config.yaml so the frontend can read them at
    build time without an API call. Rejected because IFRAME_ALLOWED_ORIGINS already lives in
    querybook_config.yaml / env vars, and requiring deployers to also add it to the public config
    would break backward compatibility for existing setups.

  2. Duplicate the value in both querybook_config.yaml and querybook_public_config.yaml.
    Rejected because maintaining the same list in two places invites config drift, which is
    especially risky for a security-sensitive setting.

  3. Current approach — lightweight API endpoint: A single source of truth
    (IFRAME_ALLOWED_ORIGINS) is read at runtime by both the server (CSP headers) and the frontend
    (via the new endpoint). No new configuration keys, no duplication, fully backward compatible.

@jasoncoffman jasoncoffman force-pushed the fix/cross-origin-postmessage branch from fb0cafd to ce69e2f Compare March 19, 2026 02:07
@jasoncoffman jasoncoffman force-pushed the fix/cross-origin-postmessage branch from ce69e2f to ddb13ab Compare March 19, 2026 02:13
@jasoncoffman jasoncoffman marked this pull request as ready for review March 19, 2026 16:29
@jasoncoffman jasoncoffman requested a review from kgopal492 March 19, 2026 16:29
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