Does this issue occur when all extensions are disabled?: Yes
- VS Code Version: 1.124.0
- OS Version: macOS 14.7.7 (Sonoma), iMac (Late 2013, Intel Core i5, 24 GB RAM)
- Note: this machine runs Sonoma via OpenCore Legacy Patcher. However, the behavior described below is reproducible from source-level logic that is platform-independent (see Root cause), so it is not specific to this hardware or to macOS.
Summary
When previewing a standalone .html file in the Integrated Browser without any folder/workspace open (empty window), the preview is blocked with:
Forbidden. File does not reside within a trusted folder.
This happens even when Workspace Trust is fully disabled, with the following user settings:
{
"security.workspace.trust.enabled": false,
"security.workspace.trust.untrustedFiles": "open",
"security.workspace.trust.emptyWindow": true
}
Setting security.workspace.trust.enabled: false is an explicit declaration that the user trusts all local content. The editor honors this (files open without any prompt), but the Integrated Browser's file:// handler does not, which is inconsistent. Rendering a file in the sandboxed browser view is arguably a weaker operation than opening it in the editor with full extension/task capabilities, yet only the former is blocked.
Additionally, because the Workspaces: Manage Workspace Trust command is hidden when security.workspace.trust.enabled is false (its precondition requires the setting to be true), the user has no discoverable way to fix the 403: the only UI that could add a trusted folder is unreachable in exactly the configuration that triggers the problem.
Steps to Reproduce
- Set
"security.workspace.trust.enabled": false in user settings.
- Open a new empty VS Code window (no folder/workspace).
- Open any local
.html file (File > Open...). It opens in the editor without any trust prompt, as expected.
- Preview it in the Integrated Browser (e.g. Show Preview in the editor title bar, or navigate to the
file:// URL in the browser tab).
- The browser renders:
Forbidden. File does not reside within a trusted folder. (HTTP 403).
- Try to add the folder as trusted:
Ctrl/Cmd+Shift+P → "Manage Workspace Trust" — the command does not appear, because Workspace Trust is disabled.
Expected Behavior
With security.workspace.trust.enabled: false, file:// navigation in the Integrated Browser should be allowed (the user has globally opted out of the trust model), or at minimum the empty-window trust settings (security.workspace.trust.emptyWindow, untrustedFiles: "open") should be honored.
Root Cause (from source)
The 403 is returned by the file:// protocol handler in
src/vs/platform/browserView/electron-main/browserSession.ts:
this.electronSession.protocol.handle(Schemas.file, request => {
const filePath = normalize(URI.parse(request.url).fsPath);
if (!BrowserSession._trustedFileRoots.findSubstr(filePath)) {
return new Response(localize('browserSession.untrustedFile',
'Forbidden. File does not reside within a trusted folder.'), { status: 403 });
}
...
});
_trustedFileRoots is populated by sendTrustedFileRoots() in
src/vs/workbench/contrib/browserView/electron-browser/browserViewWorkbenchService.ts, which only considers:
- the current workspace folders (if
isWorkspaceTrusted()), and
workspaceTrustManagementService.getTrustedUris() (the persisted "Trusted Folders & Workspaces" list).
The security.workspace.trust.enabled flag is never consulted in this computation. In an empty window there are no workspace folders (so #1 contributes nothing regardless of emptyWindow: true), and a user who has had trust disabled has an empty trusted-URI list (so #2 is empty). The result is an empty root set and an unconditional 403 for every file:// URL.
So the two trust systems are disconnected: the workbench short-circuits to "everything trusted" when the feature is disabled, but the browserView trust-roots computation has no concept of that state.
Workaround (confirmed)
- Temporarily set
"security.workspace.trust.enabled": true and reload.
- Run Workspaces: Manage Workspace Trust → "Trusted Folders & Workspaces" → Add Folder → add a parent folder of the HTML files (e.g. the user home directory).
- Set the setting back to
false and reload.
The persisted trusted-URI list (content.trust.model.key, application storage) is loaded unconditionally by getTrustedUris(), so the preview keeps working afterwards. This confirms the mechanism, but it relies on undocumented behavior and requires toggling a security setting just to reach the relevant UI.
Suggested Fix
In sendTrustedFileRoots(), when workspaceTrustEnablementService.isWorkspaceTrustEnabled() is false, either treat all local files as trusted (consistent with how the rest of the workbench behaves in that state), or honor the empty-window trust result for the file roots as well.
Does this issue occur when all extensions are disabled?: Yes
Summary
When previewing a standalone
.htmlfile in the Integrated Browser without any folder/workspace open (empty window), the preview is blocked with:This happens even when Workspace Trust is fully disabled, with the following user settings:
{ "security.workspace.trust.enabled": false, "security.workspace.trust.untrustedFiles": "open", "security.workspace.trust.emptyWindow": true }Setting
security.workspace.trust.enabled: falseis an explicit declaration that the user trusts all local content. The editor honors this (files open without any prompt), but the Integrated Browser'sfile://handler does not, which is inconsistent. Rendering a file in the sandboxed browser view is arguably a weaker operation than opening it in the editor with full extension/task capabilities, yet only the former is blocked.Additionally, because the Workspaces: Manage Workspace Trust command is hidden when
security.workspace.trust.enabledisfalse(its precondition requires the setting to betrue), the user has no discoverable way to fix the 403: the only UI that could add a trusted folder is unreachable in exactly the configuration that triggers the problem.Steps to Reproduce
"security.workspace.trust.enabled": falsein user settings..htmlfile (File > Open...). It opens in the editor without any trust prompt, as expected.file://URL in the browser tab).Forbidden. File does not reside within a trusted folder.(HTTP 403).Ctrl/Cmd+Shift+P→ "Manage Workspace Trust" — the command does not appear, because Workspace Trust is disabled.Expected Behavior
With
security.workspace.trust.enabled: false,file://navigation in the Integrated Browser should be allowed (the user has globally opted out of the trust model), or at minimum the empty-window trust settings (security.workspace.trust.emptyWindow,untrustedFiles: "open") should be honored.Root Cause (from source)
The 403 is returned by the
file://protocol handler insrc/vs/platform/browserView/electron-main/browserSession.ts:_trustedFileRootsis populated bysendTrustedFileRoots()insrc/vs/workbench/contrib/browserView/electron-browser/browserViewWorkbenchService.ts, which only considers:isWorkspaceTrusted()), andworkspaceTrustManagementService.getTrustedUris()(the persisted "Trusted Folders & Workspaces" list).The
security.workspace.trust.enabledflag is never consulted in this computation. In an empty window there are no workspace folders (so #1 contributes nothing regardless ofemptyWindow: true), and a user who has had trust disabled has an empty trusted-URI list (so #2 is empty). The result is an empty root set and an unconditional 403 for everyfile://URL.So the two trust systems are disconnected: the workbench short-circuits to "everything trusted" when the feature is disabled, but the browserView trust-roots computation has no concept of that state.
Workaround (confirmed)
"security.workspace.trust.enabled": trueand reload.falseand reload.The persisted trusted-URI list (
content.trust.model.key, application storage) is loaded unconditionally bygetTrustedUris(), so the preview keeps working afterwards. This confirms the mechanism, but it relies on undocumented behavior and requires toggling a security setting just to reach the relevant UI.Suggested Fix
In
sendTrustedFileRoots(), whenworkspaceTrustEnablementService.isWorkspaceTrustEnabled()isfalse, either treat all local files as trusted (consistent with how the rest of the workbench behaves in that state), or honor the empty-window trust result for the file roots as well.