diff --git a/src/vs/base/node/unc.d.ts b/src/vs/base/node/unc.d.ts index 1e78aba97a1..75e53310c8c 100644 --- a/src/vs/base/node/unc.d.ts +++ b/src/vs/base/node/unc.d.ts @@ -17,3 +17,9 @@ export function getUNCHostAllowlist(): string[]; * Adds one to many UNC host(s) to the allowed list in node.js. */ export function addUNCHostToAllowlist(allowedHost: string | string[]): void; + +/** + * Disables UNC Host allow list in node.js and thus disables UNC + * path validation. + */ +export function disableUNCAccessRestrictions(): void; diff --git a/src/vs/base/node/unc.js b/src/vs/base/node/unc.js index 7b046936764..7a1c9e14ac6 100644 --- a/src/vs/base/node/unc.js +++ b/src/vs/base/node/unc.js @@ -109,10 +109,19 @@ return host; } + function disableUNCAccessRestrictions() { + if (process.platform !== 'win32') { + return; + } + + process.enableUNCAccessChecks = false; + } + return { getUNCHostAllowlist, addUNCHostToAllowlist, - getUNCHost + getUNCHost, + disableUNCAccessRestrictions }; } diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 8a5181c3dab..09510958be4 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { app, BrowserWindow, dialog, protocol, session, Session, systemPreferences, WebFrameMain } from 'electron'; -import { addUNCHostToAllowlist } from 'vs/base/node/unc'; +import { addUNCHostToAllowlist, disableUNCAccessRestrictions } from 'vs/base/node/unc'; import { validatedIpcMain } from 'vs/base/parts/ipc/electron-main/ipcMain'; import { hostname, release } from 'os'; import { VSBuffer } from 'vs/base/common/buffer'; @@ -320,7 +320,11 @@ export class CodeApplication extends Disposable { //#region UNC Host Allowlist (Windows) if (isWindows) { - addUNCHostToAllowlist(this.configurationService.getValue('security.allowedUNCHosts')); + if (this.configurationService.getValue('security.restrictUNCAccess') === false) { + disableUNCAccessRestrictions(); + } else { + addUNCHostToAllowlist(this.configurationService.getValue('security.allowedUNCHosts')); + } } //#endregion diff --git a/src/vs/server/node/remoteExtensionHostAgentCli.ts b/src/vs/server/node/remoteExtensionHostAgentCli.ts index 561637d13b9..5f6c64c3a1d 100644 --- a/src/vs/server/node/remoteExtensionHostAgentCli.ts +++ b/src/vs/server/node/remoteExtensionHostAgentCli.ts @@ -49,7 +49,7 @@ import { ExtensionsProfileScannerService } from 'vs/platform/extensionManagement import { LogService } from 'vs/platform/log/common/logService'; import { LoggerService } from 'vs/platform/log/node/loggerService'; import { localize } from 'vs/nls'; -import { addUNCHostToAllowlist } from 'vs/base/node/unc'; +import { addUNCHostToAllowlist, disableUNCAccessRestrictions } from 'vs/base/node/unc'; class CliMain extends Disposable { @@ -72,7 +72,11 @@ class CliMain extends Disposable { // On Windows, configure the UNC allow list based on settings if (isWindows) { - addUNCHostToAllowlist(configurationService.getValue('security.allowedUNCHosts')); + if (configurationService.getValue('security.restrictUNCAccess') === false) { + disableUNCAccessRestrictions(); + } else { + addUNCHostToAllowlist(configurationService.getValue('security.allowedUNCHosts')); + } } try { diff --git a/src/vs/server/node/remoteExtensionHostAgentServer.ts b/src/vs/server/node/remoteExtensionHostAgentServer.ts index 743bbd6145a..86fa775403e 100644 --- a/src/vs/server/node/remoteExtensionHostAgentServer.ts +++ b/src/vs/server/node/remoteExtensionHostAgentServer.ts @@ -23,7 +23,7 @@ import { createRegExp, escapeRegExpCharacters } from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; import { generateUuid } from 'vs/base/common/uuid'; import { findFreePort } from 'vs/base/node/ports'; -import { addUNCHostToAllowlist } from 'vs/base/node/unc'; +import { addUNCHostToAllowlist, disableUNCAccessRestrictions } from 'vs/base/node/unc'; import { PersistentProtocol } from 'vs/base/parts/ipc/common/ipc.net'; import { NodeSocket, WebSocketNodeSocket } from 'vs/base/parts/ipc/node/ipc.net'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -719,7 +719,11 @@ export async function createServer(address: string | net.AddressInfo | null, arg const configurationService = accessor.get(IConfigurationService); if (platform.isWindows) { - addUNCHostToAllowlist(configurationService.getValue('security.allowedUNCHosts')); + if (configurationService.getValue('security.restrictUNCAccess') === false) { + disableUNCAccessRestrictions(); + } else { + addUNCHostToAllowlist(configurationService.getValue('security.allowedUNCHosts')); + } } }); diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index cef5e663bd6..2dd6519071f 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -704,6 +704,13 @@ const registry = Registry.as(ConfigurationExtensions.Con 'markdownDescription': localize('security.allowedUNCHosts', 'A set of UNC host names (without leading or trailing backslash, for example `192.168.0.1` or `my-server`) to allow without user confirmation. If a UNC host is being accessed that is not allowed via this setting or has not been acknowledged via user confirmation, an error will occur and the operation stopped. A restart is required when changing this setting. Find out more about this setting at https://aka.ms/vscode-windows-unc.'), 'included': isWeb ? true /* web maybe connected to a windows machine */ : isWindows, 'scope': ConfigurationScope.MACHINE + }, + 'security.restrictUNCAccess': { + 'type': 'boolean', + 'default': true, + 'markdownDescription': localize('security.restrictUNCAccess', 'If enabled, only allowes access to UNC host names that are allowed by the `#security.allowedUNCHosts#` setting or after user confirmation. Find out more about this setting at https://aka.ms/vscode-windows-unc.'), + 'included': isWeb ? true /* web maybe connected to a windows machine */ : isWindows, + 'scope': ConfigurationScope.MACHINE } } }); diff --git a/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts b/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts index c4918b91c13..9942f0f95c3 100644 --- a/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts +++ b/src/vs/workbench/contrib/relauncher/browser/relauncher.contribution.ts @@ -25,7 +25,7 @@ interface IConfiguration extends IWindowsConfiguration { update?: { mode?: string }; debug?: { console?: { wordWrap?: boolean } }; editor?: { accessibilitySupport?: 'on' | 'off' | 'auto' }; - security?: { workspace?: { trust?: { enabled?: boolean } } }; + security?: { workspace?: { trust?: { enabled?: boolean } }; restrictUNCAccess?: boolean }; window: IWindowSettings & { experimental?: { windowControlsOverlay?: { enabled?: boolean } } }; workbench?: { enableExperiments?: boolean }; _extensionsGallery?: { enablePPE?: boolean }; @@ -43,7 +43,8 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo 'editor.accessibilitySupport', 'security.workspace.trust.enabled', 'workbench.enableExperiments', - '_extensionsGallery.enablePPE' + '_extensionsGallery.enablePPE', + 'security.restrictUNCAccess' ]; private readonly titleBarStyle = new ChangeObserver<'native' | 'custom'>('string'); @@ -56,6 +57,7 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo private readonly workspaceTrustEnabled = new ChangeObserver('boolean'); private readonly experimentsEnabled = new ChangeObserver('boolean'); private readonly enablePPEExtensionsGallery = new ChangeObserver('boolean'); + private readonly restrictUNCAccess = new ChangeObserver('boolean'); constructor( @IHostService private readonly hostService: IHostService, @@ -112,6 +114,9 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo // Workspace trust processChanged(this.workspaceTrustEnabled.handleChange(config?.security?.workspace?.trust?.enabled)); + + // UNC host access restrictions + processChanged(this.restrictUNCAccess.handleChange(config?.security?.restrictUNCAccess)); } // Experiments