fix(webui): respect full access in file preview

This commit is contained in:
chengyongru
2026-07-09 10:42:43 +08:00
committed by Xubin Ren
parent 0ae28571e7
commit bbd4f4054b
2 changed files with 40 additions and 3 deletions
+2 -2
View File
@@ -28,7 +28,7 @@ def file_preview_payload(
scope: WorkspaceScope,
max_bytes: int = MAX_FILE_PREVIEW_BYTES,
) -> dict[str, Any]:
"""Return a text preview for a file inside the session workspace."""
"""Return a text preview for a file allowed by the session workspace scope."""
path = _clean_preview_path(raw_path)
if not path:
@@ -40,7 +40,7 @@ def file_preview_payload(
resolved = resolve_allowed_path(
path,
workspace=scope.project_path,
allowed_root=scope.project_path,
allowed_root=scope.project_path if scope.restrict_to_workspace else None,
strict=True,
)
except FileNotFoundError as e:
+38 -1
View File
@@ -2914,7 +2914,11 @@ def test_handle_file_preview_rejects_paths_outside_workspace(tmp_path) -> None:
outside = tmp_path / "secret.py"
outside.write_text("secret = True\n", encoding="utf-8")
gateway = _basic_handler(MagicMock(), workspace_path=workspace)
gateway = _basic_handler(
MagicMock(),
workspace_path=workspace,
default_restrict_to_workspace=True,
)
gateway.tokens.api_tokens["tok"] = time.monotonic() + 300.0
key = "websocket:file-preview"
enc = quote(key, safe="")
@@ -2928,6 +2932,39 @@ def test_handle_file_preview_rejects_paths_outside_workspace(tmp_path) -> None:
assert resp.status_code == 403
def test_handle_file_preview_allows_paths_outside_workspace_in_full_access(tmp_path) -> None:
from urllib.parse import quote
from websockets.datastructures import Headers
from websockets.http11 import Request
workspace = tmp_path / "workspace"
workspace.mkdir()
outside = tmp_path / "notes.py"
outside.write_text("value = 42\n", encoding="utf-8")
gateway = _basic_handler(
MagicMock(),
workspace_path=workspace,
default_restrict_to_workspace=False,
)
gateway.tokens.api_tokens["tok"] = time.monotonic() + 300.0
key = "websocket:file-preview"
enc = quote(key, safe="")
req = Request(
f"/api/sessions/{enc}/file-preview?path={quote(str(outside), safe='')}",
Headers([("Authorization", "Bearer tok")]),
)
resp = gateway.http._handle_file_preview(req, enc)
assert resp.status_code == 200
body = json.loads(resp.body.decode())
assert body["path"] == str(outside.resolve())
assert body["display_path"] == outside.resolve().as_posix()
assert body["content"].splitlines() == ["value = 42"]
def test_handle_webui_thread_get_backfills_legacy_missing_user_rows(
tmp_path,
monkeypatch,