Skip to content

fix(gateway): sandbox workspace assistant-media SVG documents - #1

Open
SebTardif wants to merge 1 commit into
mainfrom
fix/workspace-svg-assistant-media-sandbox
Open

fix(gateway): sandbox workspace assistant-media SVG documents#1
SebTardif wants to merge 1 commit into
mainfrom
fix/workspace-svg-assistant-media-sandbox

Conversation

@SebTardif

@SebTardif SebTardif commented Sep 11, 2026

Copy link
Copy Markdown
Owner

What Problem This Solves

GET /__openclaw__/assistant-media applies the image-document sandbox CSP only when the file is outside allowed roots. A workspace SVG is still served as image/svg+xml with Content-Disposition: inline and the Control UI CSP (script-src 'self'). Opening that URL as a top-level document is same-origin with Control UI, so a same-origin script in the SVG can run. Outside SVG already gets default-src 'none'; sandbox, which blocks that.

This change was first reported privately as GHSA-j833-88j9-76q7. The same one-line sandbox fix was prepared on the temporary private fork openclaw/openclaw-ghsa-j833-88j9-76q7. The advisory was later closed unpublished. The remediating public PR against openclaw/openclaw is already #144333. This PR is the public record on the SebTardif fork. Do not merge this into fork main as a substitute for that upstream PR.

Why This Change Was Made

A live browser load of the two header policies shows the script-execution gap. Workspace CSP fetched /probe.js and /hit. Sandbox CSP did not fetch /probe.js. Apply the existing image sandbox to every assistant-media image, including workspace SVG.

User Impact

Workspace diagrams that rely on inline CSS or external SVG resources may render more strictly when opened as a top-level document. <img> embedding is unchanged. Outside-root images already used this sandbox.

Evidence

Live browser (Edge CDP) against a local server that reused the Control UI CSP vs the image sandbox CSP. Same SVG, same script href.

SERVER http://127.0.0.1:50410
HTTP "GET /workspace.svg HTTP/1.1" 200 -
HTTP "GET /probe.js HTTP/1.1" 200 -
HTTP "GET /hit?from=%2Fworkspace.svg HTTP/1.1" 204 -
HTTP "GET /outside.svg HTTP/1.1" 200 -
RESULT {'workspace': True, 'outside': False}
DEMO: script ran under Control UI CSP; sandbox blocked it

After the header change, workspace SVG byte responses also set content-security-policy containing sandbox.

Real behavior proof

  • Behavior or issue addressed: Workspace assistant-media SVG was a same-origin document without the image sandbox, so a same-origin script in that SVG could run. Sandboxed outside SVG could not.

  • Real environment tested: Windows 11, Edge via CDP on 127.0.0.1:9222, worktree C:/tmp/oc-f074-public at the patched tip.

  • Exact steps or command run after this patch:

    python C:/tmp/svg-csp-demo.py
  • Evidence after fix: terminal output from the header replay:

    HTTP "GET /workspace.svg HTTP/1.1" 200 -
    HTTP "GET /probe.js HTTP/1.1" 200 -
    HTTP "GET /hit?from=%2Fworkspace.svg HTTP/1.1" 204 -
    HTTP "GET /outside.svg HTTP/1.1" 200 -
    RESULT {'workspace': True, 'outside': False}
  • Observed result after fix: Control UI CSP lets the SVG load /probe.js and post /hit. Image sandbox does not load /probe.js. Workspace SVG now gets that sandbox header.

  • What was not tested: A full Gateway plus Control UI lightbox click with a live operator session.

Summary

Same one-line change as openclaw#144333 (if (mediaKind === "image")). First filed as GHSA-j833-88j9-76q7 with the fix on the private advisory fork. Public fork record only.

Apply the existing image-document sandbox to every assistant-media
image, not only files outside allowed roots. Workspace SVG opened
as a document otherwise keeps Control UI script-src 'self'.

Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
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.

1 participant