Fix workspace open in browser inline sandbox

This commit is contained in:
xz-dev
2026-06-01 10:50:22 +08:00
committed by nesquena-hermes
parent 18eea5b2ab
commit 239f913485
3 changed files with 34 additions and 4 deletions

View File

@@ -8677,10 +8677,11 @@ def _handle_file_raw(handler, parsed):
# CSP sandbox directive applies the same isolation server-side: without
# allow-same-origin, the document is treated as a unique opaque origin and
# cannot read WebUI cookies, localStorage, or postMessage to the parent.
csp = "sandbox allow-scripts allow-popups allow-popups-to-escape-sandbox" if html_inline_ok else None
sandbox_csp = "sandbox allow-scripts allow-popups allow-popups-to-escape-sandbox"
csp = sandbox_csp if (inline_preview and not force_download and disposition == "inline") else None
# _serve_file_bytes sends Content-Security-Policy when csp is set.
if html_inline_ok:
return _serve_inline_html_preview(handler, target, "no-store", csp=csp)
return _serve_inline_html_preview(handler, target, "no-store", csp=sandbox_csp)
return _serve_file_bytes(handler, target, mime, disposition, "no-store", csp=csp)

View File

@@ -675,6 +675,6 @@ function renderFileBreadcrumb(filePath) {
function openInBrowser(){
if(!_previewCurrentPath||!S.session) return;
const url=`api/file/raw?session_id=${encodeURIComponent(S.session.session_id)}&path=${encodeURIComponent(_previewCurrentPath)}`;
window.open(url,'_blank');
const url=`api/file/raw?session_id=${encodeURIComponent(S.session.session_id)}&path=${encodeURIComponent(_previewCurrentPath)}&inline=1`;
window.open(url,'_blank','noopener');
}

View File

@@ -33,6 +33,23 @@ def test_iframe_uses_inline_param():
)
def test_open_in_browser_uses_unconditional_inline_param():
"""Workspace Open in browser must use the explicit inline/sandbox open path."""
content = _get_workspace_js()
idx = content.find("function openInBrowser()")
assert idx != -1, "openInBrowser() must exist"
block = content[idx:idx + 700]
assert "&inline=1" in block, (
"openInBrowser() must include inline=1 so HTML opens instead of downloading"
)
assert "download=1" not in block, (
"openInBrowser() must not reuse the Download button path"
)
assert "window.open(url,'_blank','noopener')" in block or 'window.open(url,"_blank","noopener")' in block, (
"openInBrowser() should use noopener for the new tab"
)
def test_html_preview_iframe_exists_in_html():
"""The previewHtmlIframe element must be present in index.html."""
content = _get_index_html()
@@ -105,3 +122,15 @@ def test_inline_html_response_sets_csp_sandbox():
assert "allow-same-origin" not in line, (
"CSP sandbox must NOT include allow-same-origin — that would defeat the isolation"
)
def test_file_raw_inline_responses_use_sandbox_csp():
"""The explicit inline-open contract should sandbox non-download raw files."""
content = _get_routes_content()
idx = content.find("def _handle_file_raw")
assert idx != -1, "_handle_file_raw not found"
block = content[idx:idx + 2200]
assert "sandbox_csp" in block
assert "inline_preview" in block
assert "disposition == \"inline\"" in block
assert "csp=sandbox_csp" in block or "csp=csp" in block