From 1590fd3de051b385c0e95fa67aef4563f396acbd Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sat, 6 Jun 2026 18:58:07 +0200 Subject: [PATCH 01/42] docs: document IFRAME_CSP on the Artifacts page IFRAME_CSP (a Content-Security-Policy injected into artifact and preview srcdoc iframes) is already covered in the env reference and the hardening guide. This fills the user-facing gap: an artifact-CSP section and a blank-preview troubleshooting entry on the Artifacts page, linking to both, with the correct variable name, scope, and prepend-first-wins behaviour. Based on the intent of PR #1249. Co-Authored-By: michaellrowley <13807564+michaellrowley@users.noreply.github.com> Co-Authored-By: Claude Opus 4.8 (1M context) --- .../chat-features/code-execution/artifacts.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/features/chat-conversations/chat-features/code-execution/artifacts.md b/docs/features/chat-conversations/chat-features/code-execution/artifacts.md index 5d2bcd2fbe..187a8e268d 100644 --- a/docs/features/chat-conversations/chat-features/code-execution/artifacts.md +++ b/docs/features/chat-conversations/chat-features/code-execution/artifacts.md @@ -32,6 +32,22 @@ When Open WebUI creates an Artifact, you'll see the content displayed in a dedic - **Updates**: Open WebUI may update an existing Artifact based on your messages. The Artifact window will display the latest content. - **Actions**: Access additional actions for the Artifact, such as copying the content or opening the artifact in full screen, located in the lower right corner of the Artifact. +## Securing artifact previews with a CSP + +Artifact previews render inside a sandboxed `srcdoc` iframe. For tighter control over what that generated HTML can do (outbound network calls, scripts, styles), inject a dedicated Content Security Policy into the preview with the [`IFRAME_CSP`](/reference/env-configuration#iframe_csp) environment variable, separate from the main app's `CONTENT_SECURITY_POLICY`. + +It is empty by default (the iframe `sandbox` already provides baseline isolation) and applies to **every** `srcdoc` iframe in the UI: Artifacts, code/HTML previews, file previews and citation modals. When set, Open WebUI prepends a `` tag to the iframe document, and per the CSP spec the first policy wins, so it overrides any CSP the generated HTML already declares. A reasonable starting point: + +```bash +IFRAME_CSP=default-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob:; connect-src 'none' +``` + +That keeps inline scripts and styles working (most artifacts need them) while blocking `fetch` / `XMLHttpRequest` / `WebSocket`, so an artifact cannot quietly call out to the network. + +:::tip Start permissive, then tighten +An overly strict policy can make a preview appear blank, since many artifacts rely on inline ` ``` -:::warning Requires `allowSameOrigin` — otherwise `window.args` is silently `undefined` +:::warning Requires `allowSameOrigin`, otherwise `window.args` is silently `undefined` The args are injected from the parent page via `iframe.contentWindow.args = ...`, which the browser blocks under same-origin policy unless the iframe sandbox carries `allow-same-origin`. That is gated by the per-user **Settings → Interface → "iframe Sandbox Allow Same Origin"** toggle, which is **off by default**. If `window.args` comes back undefined and you have not changed this setting, that is the cause: turn it on and reload. See [allowSameOrigin](#allowsameorigin) above for the security trade-off. ::: :::note Where `window.args` is set, and where it is not -- ✅ **Tool method returning `HTMLResponse` or `(HTMLResponse, context)` tuple** — rendered inline at the "View Result from..." tool call indicator. `window.args` is injected (subject to the `allowSameOrigin` requirement above). -- ❌ **`__event_emitter__({"type": "embeds", "data": {"embeds": [...]}})`** — rendered through the chat-controls Embeds panel, which does not wire `args` at all. `window.args` will always be undefined here, regardless of sandbox settings. This is by design: the embeds-event path has no tool call attached, so there are no args to inject. -- ❌ **Action embeds** — triggered by the user, not the model, so there are no model-supplied args to inject. +- ✅ **Tool method returning `HTMLResponse` or `(HTMLResponse, context)` tuple**: rendered inline at the "View Result from..." tool call indicator. `window.args` is injected (subject to the `allowSameOrigin` requirement above). +- ❌ **`__event_emitter__({"type": "embeds", "data": {"embeds": [...]}})`**: rendered through the chat-controls Embeds panel, which does not wire `args` at all. `window.args` will always be undefined here, regardless of sandbox settings. This is by design: the embeds-event path has no tool call attached, so there are no args to inject. +- ❌ **Action embeds**: triggered by the user, not the model, so there are no model-supplied args to inject. If you need to pass dynamic data into an embed rendered via either of the ❌ paths, use the [Payload Requests](#payload-requests) pattern above instead. ::: ### Auto-Injected Libraries -When `allowSameOrigin` is enabled, the iframe component auto-detects usage of certain libraries in your HTML and injects them automatically — no CDN `