openclaw - 💡(How to fix) Fix Control UI CSP/X-Frame-Options has no opt-in for same-origin framing (regression in 2026.5.5) [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#78577Fetched 2026-05-07 03:35:06
View on GitHub
Comments
1
Participants
2
Timeline
1
Reactions
2
Author
Timeline (top)
commented ×1

In 2026.5.5, dist/control-ui-*.js hard-codes X-Frame-Options: DENY and Content-Security-Policy: ...; frame-ancestors 'none'; ... on all control-UI responses with no config knob to relax them.

This breaks any same-origin iframe embed of the control UI — including deployments that intentionally ship a custom dashboard on the same host and iframe the control UI as a drill-down panel.

Root Cause

Before 2026.5.5 this worked. After upgrading, the iframe fails to load in every browser because the security headers forbid any frame ancestor — including the origin's own documents. There is no opt-in to allow 'self' framing.

Fix Action

Workaround

Patch the installed bundle post-install:

  • frame-ancestors 'none'frame-ancestors 'self'
  • X-Frame-Options: DENYX-Frame-Options: SAMEORIGIN

Must be reapplied after every npm install -g openclaw@latest.

Code Example

"controlUi": {
  "frameAncestors": ["self"]   // default: ["none"]
}
RAW_BUFFERClick to expand / collapse

Summary

In 2026.5.5, dist/control-ui-*.js hard-codes X-Frame-Options: DENY and Content-Security-Policy: ...; frame-ancestors 'none'; ... on all control-UI responses with no config knob to relax them.

This breaks any same-origin iframe embed of the control UI — including deployments that intentionally ship a custom dashboard on the same host and iframe the control UI as a drill-down panel.

Impact

We run the OpenClaw control UI at https://example/ and a separate dashboard at https://example/chatsworth/. The dashboard embeds the control UI via <iframe src="/?embed=..."> for a full-chat drill-down view.

Before 2026.5.5 this worked. After upgrading, the iframe fails to load in every browser because the security headers forbid any frame ancestor — including the origin's own documents. There is no opt-in to allow 'self' framing.

Reproduction

  1. Upgrade to 2026.5.5.
  2. Serve the control UI at https://example/.
  3. From another same-origin page at https://example/app/, embed the control UI in an <iframe>.
  4. The iframe shows a blank page; devtools show:
    • Refused to display 'https://example/' in a frame because it set 'X-Frame-Options' to 'deny'.
    • Refused to frame 'https://example/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'none'".
  5. curl -I https://example/ confirms both headers on every control UI response.

Requested

Add a gateway config flag under gateway.controlUi, e.g.:

"controlUi": {
  "frameAncestors": ["self"]   // default: ["none"]
}

Semantics:

  • When the list equals ["self"] → emit frame-ancestors 'self' + X-Frame-Options: SAMEORIGIN.
  • When the list is empty or ["none"] → keep current behavior ('none' / DENY).
  • When the list is wider (e.g. ["self", "https://trusted.example"]) → emit the corresponding CSP and omit X-Frame-Options (which can't express multiple origins).

This keeps the hardened default and gives operators a documented way to relax it for legitimate same-origin dashboard embeds.

Notes

  • gateway.controlUi.embedSandbox controls the hosted embed sandbox (for /__openclaw__/canvas etc.) and does NOT affect the root control UI CSP.
  • gateway.controlUi.allowedOrigins gates WebSocket origin checks — different concern, also does not fix this.
  • The existing Permissions-Policy / COOP / nosniff / Referrer-Policy headers are fine and should stay.

Code locations (from installed dist/)

  • Header builder: buildControlUiCspHeader() in dist/control-ui-<hash>.js (src equivalent presumably under src/gateway/control-ui-*.ts).
  • Header setter: applyControlUiSecurityHeaders(res) in the same bundle.

Both currently take no parameters and emit constants.

Workaround

Patch the installed bundle post-install:

  • frame-ancestors 'none'frame-ancestors 'self'
  • X-Frame-Options: DENYX-Frame-Options: SAMEORIGIN

Must be reapplied after every npm install -g openclaw@latest.

Version

OpenClaw 2026.5.5 (confirmed broken). Did not exhibit under whatever we were running before 2026.5.4; I can bisect if helpful.

Environment

  • Linux (Ubuntu 25.10)
  • Installed via npm install -g openclaw@latest
  • Gateway served on loopback behind a Tailscale-serve reverse proxy terminating HTTPS.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix Control UI CSP/X-Frame-Options has no opt-in for same-origin framing (regression in 2026.5.5) [1 comments, 2 participants]