Rename agent sandbox settings (#307237)

* Rename agent sandbox settings

* refactoring for review comments

* Update src/vs/workbench/contrib/terminalContrib/chatAgentTools/common/terminalChatAgentToolsConfiguration.ts

Update for deprecation

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
dileepyavan
2026-04-01 13:56:32 -07:00
committed by GitHub
parent 1d3e82fd38
commit cc9f34504b
10 changed files with 152 additions and 162 deletions

View File

@@ -11,8 +11,8 @@ import { DeferredPromise, assertNoRpc, closeAllEditors, disposeAll } from '../ut
const isWindows = process.platform === 'win32';
const isMacOS = process.platform === 'darwin';
const sandboxFileSystemSetting = isMacOS
? 'chat.agent.sandboxFileSystem.mac'
: 'chat.agent.sandboxFileSystem.linux';
? 'chat.agent.sandbox.fileSystem.mac'
: 'chat.agent.sandbox.fileSystem.linux';
/**
* Extracts all text content from a LanguageModelToolResult.
@@ -274,12 +274,12 @@ function extractTextContent(result: vscode.LanguageModelToolResult): string {
setup(async () => {
const configuration = vscode.workspace.getConfiguration();
await configuration.update('chat.agent.sandbox', true, vscode.ConfigurationTarget.Global);
await configuration.update('chat.agent.sandbox.enabled', 'on', vscode.ConfigurationTarget.Global);
});
teardown(async () => {
const configuration = vscode.workspace.getConfiguration();
await configuration.update('chat.agent.sandbox', undefined, vscode.ConfigurationTarget.Global);
await configuration.update('chat.agent.sandbox.enabled', undefined, vscode.ConfigurationTarget.Global);
});
// Flaky: #305722
@@ -296,7 +296,7 @@ function extractTextContent(result: vscode.LanguageModelToolResult): string {
this.timeout(60000);
const configuration = vscode.workspace.getConfiguration();
await configuration.update('chat.agent.sandboxNetwork.allowedDomains', ['example.com'], vscode.ConfigurationTarget.Global);
await configuration.update('chat.agent.sandbox.allowedNetworkDomains', ['example.com'], vscode.ConfigurationTarget.Global);
try {
const output = await invokeRunInTerminal('curl -s --max-time 5 https://example.com');
const trimmed = output.trim();
@@ -306,7 +306,7 @@ function extractTextContent(result: vscode.LanguageModelToolResult): string {
];
assert.ok(acceptable.some(value => trimmed.includes(value) || trimmed === value), `Unexpected output: ${JSON.stringify(trimmed)}`);
} finally {
await configuration.update('chat.agent.sandboxNetwork.allowedDomains', undefined, vscode.ConfigurationTarget.Global);
await configuration.update('chat.agent.sandbox.allowedNetworkDomains', undefined, vscode.ConfigurationTarget.Global);
}
});
@@ -347,7 +347,7 @@ function extractTextContent(result: vscode.LanguageModelToolResult): string {
? `/bin/bash: /tmp/${marker}.txt: Operation not permitted`
: `/usr/bin/bash: line 1: /tmp/${marker}.txt: Read-only file system`;
const sandboxBody = [
`- If it would be reasonable to extend the sandbox rules, work with the user to update allowWrite for file system access problems in ${sandboxFileSystemSetting}, or to add required domains to chat.agent.sandboxNetwork.allowedDomains.`,
`- If it would be reasonable to extend the sandbox rules, work with the user to update allowWrite for file system access problems in ${sandboxFileSystemSetting}, or to add required domains to chat.agent.sandbox.allowedNetworkDomains.`,
'- Otherwise, immediately retry the command with requestUnsandboxedExecution=true. Do NOT ask the user \u2014 setting this flag automatically shows a confirmation prompt to the user.',
'',
'Here is the output of the command:',

View File

@@ -445,6 +445,7 @@ class ConfigurationTelemetryContribution extends Disposable implements IWorkbenc
}>('terminal.integrated.suggest.enabled', { settingValue: this.getValueToReport(key, target), source });
return;
case TerminalContribSettingId.AgentSandboxEnabled:
case TerminalContribSettingId.DeprecatedAgentSandboxEnabled:
this.telemetryService.publicLog2<UpdatedSettingEvent, {
owner: 'isidorn';
comment: 'This is used to know if agent sandbox is enabled or not';

View File

@@ -712,6 +712,56 @@ export async function registerTerminalConfiguration(getFontSnippets: () => Promi
Registry.as<IConfigurationMigrationRegistry>(WorkbenchExtensions.ConfigurationMigration)
.registerConfigurationMigrations([{
key: TerminalContribSettingId.DeprecatedAgentSandboxEnabled,
migrateFn: (value: boolean, valueAccessor) => {
const configurationKeyValuePairs: ConfigurationKeyValuePairs = [];
if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxEnabled) === undefined) {
configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxEnabled, { value: value ? 'on' : 'off' }]);
}
configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedAgentSandboxEnabled, { value: undefined }]);
return configurationKeyValuePairs;
}
}, {
key: TerminalContribSettingId.DeprecatedAgentSandboxNetworkAllowedDomains,
migrateFn: (value: string[], valueAccessor) => {
const configurationKeyValuePairs: ConfigurationKeyValuePairs = [];
if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxNetworkAllowedDomains) === undefined) {
configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxNetworkAllowedDomains, { value }]);
}
configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedAgentSandboxNetworkAllowedDomains, { value: undefined }]);
return configurationKeyValuePairs;
}
}, {
key: TerminalContribSettingId.DeprecatedAgentSandboxNetworkDeniedDomains,
migrateFn: (value: string[], valueAccessor) => {
const configurationKeyValuePairs: ConfigurationKeyValuePairs = [];
if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxNetworkDeniedDomains) === undefined) {
configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxNetworkDeniedDomains, { value }]);
}
configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedAgentSandboxNetworkDeniedDomains, { value: undefined }]);
return configurationKeyValuePairs;
}
}, {
key: TerminalContribSettingId.DeprecatedAgentSandboxLinuxFileSystem,
migrateFn: (value: { denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }, valueAccessor) => {
const configurationKeyValuePairs: ConfigurationKeyValuePairs = [];
if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxLinuxFileSystem) === undefined) {
configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxLinuxFileSystem, { value }]);
}
configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedAgentSandboxLinuxFileSystem, { value: undefined }]);
return configurationKeyValuePairs;
}
}, {
key: TerminalContribSettingId.DeprecatedAgentSandboxMacFileSystem,
migrateFn: (value: { denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }, valueAccessor) => {
const configurationKeyValuePairs: ConfigurationKeyValuePairs = [];
if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxMacFileSystem) === undefined) {
configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxMacFileSystem, { value }]);
}
configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedAgentSandboxMacFileSystem, { value: undefined }]);
return configurationKeyValuePairs;
}
}, {
key: TerminalSettingId.EnableBell,
migrateFn: (enableBell, accessor) => {
const configurationKeyValuePairs: ConfigurationKeyValuePairs = [];
@@ -725,70 +775,3 @@ Registry.as<IConfigurationMigrationRegistry>(WorkbenchExtensions.ConfigurationMi
return configurationKeyValuePairs;
}
}]);
Registry.as<IConfigurationMigrationRegistry>(WorkbenchExtensions.ConfigurationMigration)
.registerConfigurationMigrations([{
key: TerminalContribSettingId.DeprecatedTerminalSandboxEnabled,
migrateFn: (value: boolean, valueAccessor) => {
const configurationKeyValuePairs: ConfigurationKeyValuePairs = [];
if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxEnabled) === undefined) {
configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxEnabled, { value }]);
}
configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedTerminalSandboxEnabled, { value: undefined }]);
return configurationKeyValuePairs;
}
}, {
key: TerminalContribSettingId.DeprecatedTerminalSandboxNetwork,
migrateFn: (value: { allowedDomains?: string[]; deniedDomains?: string[] }, valueAccessor) => {
const configurationKeyValuePairs: ConfigurationKeyValuePairs = [];
if (value?.allowedDomains !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxNetworkAllowedDomains) === undefined) {
configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxNetworkAllowedDomains, { value: value.allowedDomains }]);
}
if (value?.deniedDomains !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxNetworkDeniedDomains) === undefined) {
configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxNetworkDeniedDomains, { value: value.deniedDomains }]);
}
configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedTerminalSandboxNetwork, { value: undefined }]);
return configurationKeyValuePairs;
}
}, {
key: TerminalContribSettingId.DeprecatedTerminalSandboxNetworkAllowedDomains,
migrateFn: (value: string[], valueAccessor) => {
const configurationKeyValuePairs: ConfigurationKeyValuePairs = [];
if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxNetworkAllowedDomains) === undefined) {
configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxNetworkAllowedDomains, { value }]);
}
configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedTerminalSandboxNetworkAllowedDomains, { value: undefined }]);
return configurationKeyValuePairs;
}
}, {
key: TerminalContribSettingId.DeprecatedTerminalSandboxNetworkDeniedDomains,
migrateFn: (value: string[], valueAccessor) => {
const configurationKeyValuePairs: ConfigurationKeyValuePairs = [];
if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxNetworkDeniedDomains) === undefined) {
configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxNetworkDeniedDomains, { value }]);
}
configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedTerminalSandboxNetworkDeniedDomains, { value: undefined }]);
return configurationKeyValuePairs;
}
},
{
key: TerminalContribSettingId.DeprecatedTerminalSandboxLinuxFileSystem,
migrateFn: (value: { denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }, valueAccessor) => {
const configurationKeyValuePairs: ConfigurationKeyValuePairs = [];
if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxLinuxFileSystem) === undefined) {
configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxLinuxFileSystem, { value }]);
}
configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedTerminalSandboxLinuxFileSystem, { value: undefined }]);
return configurationKeyValuePairs;
}
}, {
key: TerminalContribSettingId.DeprecatedTerminalSandboxMacFileSystem,
migrateFn: (value: { denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }, valueAccessor) => {
const configurationKeyValuePairs: ConfigurationKeyValuePairs = [];
if (value !== undefined && valueAccessor(TerminalContribSettingId.AgentSandboxMacFileSystem) === undefined) {
configurationKeyValuePairs.push([TerminalContribSettingId.AgentSandboxMacFileSystem, { value }]);
}
configurationKeyValuePairs.push([TerminalContribSettingId.DeprecatedTerminalSandboxMacFileSystem, { value: undefined }]);
return configurationKeyValuePairs;
}
}]);

View File

@@ -47,12 +47,11 @@ export const enum TerminalContribSettingId {
ShellIntegrationTimeout = TerminalChatAgentToolsSettingId.ShellIntegrationTimeout,
OutputLocation = TerminalChatAgentToolsSettingId.OutputLocation,
AgentSandboxEnabled = TerminalChatAgentToolsSettingId.AgentSandboxEnabled,
DeprecatedTerminalSandboxNetwork = TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetwork,
DeprecatedTerminalSandboxEnabled = TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxEnabled,
DeprecatedTerminalSandboxNetworkAllowedDomains = TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkAllowedDomains,
DeprecatedTerminalSandboxNetworkDeniedDomains = TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkDeniedDomains,
DeprecatedTerminalSandboxLinuxFileSystem = TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxLinuxFileSystem,
DeprecatedTerminalSandboxMacFileSystem = TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxMacFileSystem,
DeprecatedAgentSandboxEnabled = TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxEnabled,
DeprecatedAgentSandboxNetworkAllowedDomains = TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkAllowedDomains,
DeprecatedAgentSandboxNetworkDeniedDomains = TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkDeniedDomains,
DeprecatedAgentSandboxLinuxFileSystem = TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxLinuxFileSystem,
DeprecatedAgentSandboxMacFileSystem = TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxMacFileSystem,
AgentSandboxNetworkAllowedDomains = TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains,
AgentSandboxNetworkDeniedDomains = TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains,
AgentSandboxLinuxFileSystem = TerminalChatAgentToolsSettingId.AgentSandboxLinuxFileSystem,

View File

@@ -140,11 +140,15 @@ export class ChatAgentToolsContribution extends Disposable implements IWorkbench
this._register(this._configurationService.onDidChangeConfiguration(e => {
if (
e.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxEnabled) ||
e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxEnabled) ||
e.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains) ||
e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkAllowedDomains) ||
e.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains) ||
e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxEnabled) ||
e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkAllowedDomains) ||
e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkDeniedDomains)
e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkDeniedDomains) ||
e.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxLinuxFileSystem) ||
e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxLinuxFileSystem) ||
e.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxMacFileSystem) ||
e.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxMacFileSystem)
) {
this._registerRunInTerminalTool();
}

View File

@@ -901,20 +901,20 @@ export class RunInTerminalTool extends Disposable implements IToolImpl {
private _getBlockedDomainReason(blockedDomains: string[], deniedDomains: string[] = []): string {
if (deniedDomains.length === blockedDomains.length && deniedDomains.length > 0) {
if (blockedDomains.length === 1) {
return localize('runInTerminal.unsandboxed.domain.reason.denied.single', "This command accesses {0}, which is blocked by chat.agent.sandboxNetwork.deniedDomains.", blockedDomains[0]);
return localize('runInTerminal.unsandboxed.domain.reason.denied.single', "This command accesses {0}, which is blocked by chat.agent.sandbox.deniedNetworkDomains.", blockedDomains[0]);
}
return localize('runInTerminal.unsandboxed.domain.reason.denied.multi', "This command accesses {0} and {1} more domains that are blocked by chat.agent.sandboxNetwork.deniedDomains.", blockedDomains[0], blockedDomains.length - 1);
return localize('runInTerminal.unsandboxed.domain.reason.denied.multi', "This command accesses {0} and {1} more domains that are blocked by chat.agent.sandbox.deniedNetworkDomains.", blockedDomains[0], blockedDomains.length - 1);
}
if (deniedDomains.length > 0) {
if (blockedDomains.length === 1) {
return localize('runInTerminal.unsandboxed.domain.reason.mixed.single', "This command accesses {0}, which is blocked by chat.agent.sandboxNetwork.deniedDomains or not added to chat.agent.sandboxNetwork.allowedDomains.", blockedDomains[0]);
return localize('runInTerminal.unsandboxed.domain.reason.mixed.single', "This command accesses {0}, which is blocked by chat.agent.sandbox.deniedNetworkDomains or not added to chat.agent.sandbox.allowedNetworkDomains.", blockedDomains[0]);
}
return localize('runInTerminal.unsandboxed.domain.reason.mixed.multi', "This command accesses {0} and {1} more domains that are blocked by chat.agent.sandboxNetwork.deniedDomains or not added to chat.agent.sandboxNetwork.allowedDomains.", blockedDomains[0], blockedDomains.length - 1);
return localize('runInTerminal.unsandboxed.domain.reason.mixed.multi', "This command accesses {0} and {1} more domains that are blocked by chat.agent.sandbox.deniedNetworkDomains or not added to chat.agent.sandbox.allowedNetworkDomains.", blockedDomains[0], blockedDomains.length - 1);
}
if (blockedDomains.length === 1) {
return localize('runInTerminal.unsandboxed.domain.reason.single', "This command accesses {0}, which is not permitted by the current chat.agent.sandboxNetwork configuration.", blockedDomains[0]);
return localize('runInTerminal.unsandboxed.domain.reason.single', "This command accesses {0}, which is not permitted by the current chat.agent.sandbox configuration.", blockedDomains[0]);
}
return localize('runInTerminal.unsandboxed.domain.reason.multi', "This command accesses {0} and {1} more domains that are not permitted by the current chat.agent.sandboxNetwork configuration.", blockedDomains[0], blockedDomains.length - 1);
return localize('runInTerminal.unsandboxed.domain.reason.multi', "This command accesses {0} and {1} more domains that are not permitted by the current chat.agent.sandbox configuration.", blockedDomains[0], blockedDomains.length - 1);
}
async invoke(invocation: IToolInvocation, _countTokens: CountTokensCallback, _progress: ToolProgress, token: CancellationToken): Promise<IToolResult> {

View File

@@ -20,11 +20,11 @@ export const enum TerminalChatAgentToolsSettingId {
ShellIntegrationTimeout = 'chat.tools.terminal.shellIntegrationTimeout',
AutoReplyToPrompts = 'chat.tools.terminal.autoReplyToPrompts',
OutputLocation = 'chat.tools.terminal.outputLocation',
AgentSandboxEnabled = 'chat.agent.sandbox',
AgentSandboxNetworkAllowedDomains = 'chat.agent.sandboxNetwork.allowedDomains',
AgentSandboxNetworkDeniedDomains = 'chat.agent.sandboxNetwork.deniedDomains',
AgentSandboxLinuxFileSystem = 'chat.agent.sandboxFileSystem.linux',
AgentSandboxMacFileSystem = 'chat.agent.sandboxFileSystem.mac',
AgentSandboxEnabled = 'chat.agent.sandbox.enabled',
AgentSandboxNetworkAllowedDomains = 'chat.agent.sandbox.allowedNetworkDomains',
AgentSandboxNetworkDeniedDomains = 'chat.agent.sandbox.deniedNetworkDomains',
AgentSandboxLinuxFileSystem = 'chat.agent.sandbox.fileSystem.linux',
AgentSandboxMacFileSystem = 'chat.agent.sandbox.fileSystem.mac',
PreventShellHistory = 'chat.tools.terminal.preventShellHistory',
EnforceTimeoutFromModel = 'chat.tools.terminal.enforceTimeoutFromModel',
DetachBackgroundProcesses = 'chat.tools.terminal.detachBackgroundProcesses',
@@ -34,12 +34,11 @@ export const enum TerminalChatAgentToolsSettingId {
TerminalProfileMacOs = 'chat.tools.terminal.terminalProfile.osx',
TerminalProfileWindows = 'chat.tools.terminal.terminalProfile.windows',
DeprecatedTerminalSandboxEnabled = 'chat.tools.terminal.sandbox.enabled',
DeprecatedTerminalSandboxNetwork = 'chat.tools.terminal.sandbox.network',
DeprecatedTerminalSandboxNetworkAllowedDomains = 'chat.tools.terminal.sandbox.network.allowedDomains',
DeprecatedTerminalSandboxNetworkDeniedDomains = 'chat.tools.terminal.sandbox.network.deniedDomains',
DeprecatedTerminalSandboxLinuxFileSystem = 'chat.tools.terminal.sandbox.linuxFileSystem',
DeprecatedTerminalSandboxMacFileSystem = 'chat.tools.terminal.sandbox.macFileSystem',
DeprecatedAgentSandboxEnabled = 'chat.agent.sandbox',
DeprecatedAgentSandboxNetworkAllowedDomains = 'chat.agent.sandboxNetwork.allowedDomains',
DeprecatedAgentSandboxNetworkDeniedDomains = 'chat.agent.sandboxNetwork.deniedDomains',
DeprecatedAgentSandboxLinuxFileSystem = 'chat.agent.sandboxFileSystem.linux',
DeprecatedAgentSandboxMacFileSystem = 'chat.agent.sandboxFileSystem.mac',
DeprecatedAutoApproveCompatible = 'chat.agent.terminal.autoApprove',
DeprecatedAutoApprove1 = 'chat.agent.terminal.allowList',
DeprecatedAutoApprove2 = 'chat.agent.terminal.denyList',
@@ -47,6 +46,11 @@ export const enum TerminalChatAgentToolsSettingId {
DeprecatedAutoApprove4 = 'github.copilot.chat.agent.terminal.denyList',
}
export const enum TerminalChatAgentToolsSandboxEnabledValue {
Off = 'off',
On = 'on',
}
export interface ITerminalChatAgentToolsConfiguration {
autoApprove: { [key: string]: boolean };
commandReportingAllowList: { [key: string]: boolean };
@@ -531,8 +535,13 @@ export const terminalChatAgentToolsConfiguration: IStringDictionary<IConfigurati
},
[TerminalChatAgentToolsSettingId.AgentSandboxEnabled]: {
markdownDescription: localize('agentSandbox.enabledSetting', "Controls whether agent mode uses sandboxing to restrict what tools can do. When enabled, tools like the terminal are run in a sandboxed environment to limit access to the system."),
type: 'boolean',
default: false,
type: 'string',
enum: [TerminalChatAgentToolsSandboxEnabledValue.Off, TerminalChatAgentToolsSandboxEnabledValue.On],
enumDescriptions: [
localize('agentSandbox.enabledSetting.offDescription', 'Disable sandboxing for agent mode tools.'),
localize('agentSandbox.enabledSetting.onDescription', 'Enable sandboxing for agent mode tools.'),
],
default: TerminalChatAgentToolsSandboxEnabledValue.Off,
tags: ['preview'],
restricted: true,
experiment: {
@@ -661,45 +670,35 @@ for (const id of [
};
}
terminalChatAgentToolsConfiguration[TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetwork] = {
type: 'object',
terminalChatAgentToolsConfiguration[TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkAllowedDomains] = {
type: 'array',
items: { type: 'string' },
deprecated: true,
markdownDeprecationMessage: localize(
'agentSandboxNetwork.deprecated',
'This setting has been split into {0} and {1}.',
`\`#${TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains}#\``,
`\`#${TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains}#\``,
),
markdownDeprecationMessage: localize('agentSandbox.allowedNetworkDomains.deprecated', 'Use {0} instead', `\`#${TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains}#\``),
};
terminalChatAgentToolsConfiguration[TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxEnabled] = {
terminalChatAgentToolsConfiguration[TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkDeniedDomains] = {
type: 'array',
items: { type: 'string' },
deprecated: true,
markdownDeprecationMessage: localize('agentSandbox.deniedNetworkDomains.deprecated', 'Use {0} instead', `\`#${TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains}#\``),
};
terminalChatAgentToolsConfiguration[TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxLinuxFileSystem] = {
type: 'object',
deprecated: true,
markdownDeprecationMessage: localize('agentSandbox.fileSystemLinux.deprecated', 'Use {0} instead', `\`#${TerminalChatAgentToolsSettingId.AgentSandboxLinuxFileSystem}#\``),
};
terminalChatAgentToolsConfiguration[TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxMacFileSystem] = {
type: 'object',
deprecated: true,
markdownDeprecationMessage: localize('agentSandbox.fileSystemMac.deprecated', 'Use {0} instead', `\`#${TerminalChatAgentToolsSettingId.AgentSandboxMacFileSystem}#\``),
};
terminalChatAgentToolsConfiguration[TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxEnabled] = {
type: 'boolean',
deprecated: true,
markdownDeprecationMessage: localize('agentSandboxEnabled.deprecated', 'Use {0} instead', `\`#${TerminalChatAgentToolsSettingId.AgentSandboxEnabled}#\``),
};
terminalChatAgentToolsConfiguration[TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkAllowedDomains] = {
type: 'array',
items: { type: 'string' },
deprecated: true,
markdownDeprecationMessage: localize('agentSandboxNetworkAllowedDomains.deprecated', 'Use {0} instead', `\`#${TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains}#\``),
};
terminalChatAgentToolsConfiguration[TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkDeniedDomains] = {
type: 'array',
items: { type: 'string' },
deprecated: true,
markdownDeprecationMessage: localize('agentSandboxNetworkDeniedDomains.deprecated', 'Use {0} instead', `\`#${TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains}#\``),
};
terminalChatAgentToolsConfiguration[TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxLinuxFileSystem] = {
type: 'object',
deprecated: true,
markdownDeprecationMessage: localize('agentSandboxLinuxFileSystem.deprecated', 'Use {0} instead', `\`#${TerminalChatAgentToolsSettingId.AgentSandboxLinuxFileSystem}#\``),
};
terminalChatAgentToolsConfiguration[TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxMacFileSystem] = {
type: 'object',
deprecated: true,
markdownDeprecationMessage: localize('agentSandboxMacFileSystem.deprecated', 'Use {0} instead', `\`#${TerminalChatAgentToolsSettingId.AgentSandboxMacFileSystem}#\``),
included: false,
markdownDeprecationMessage: localize('agentSandbox.enabled.deprecated', 'Use {0} instead', `\`#${TerminalChatAgentToolsSettingId.AgentSandboxEnabled}#\``),
};

View File

@@ -20,7 +20,7 @@ import { IFileService } from '../../../../../platform/files/common/files.js';
import { createDecorator } from '../../../../../platform/instantiation/common/instantiation.js';
import { ILogService } from '../../../../../platform/log/common/log.js';
import { IRemoteAgentService } from '../../../../services/remote/common/remoteAgentService.js';
import { TerminalChatAgentToolsSettingId } from './terminalChatAgentToolsConfiguration.js';
import { TerminalChatAgentToolsSandboxEnabledValue, TerminalChatAgentToolsSettingId } from './terminalChatAgentToolsConfiguration.js';
import { IRemoteAgentEnvironment } from '../../../../../platform/remote/common/remoteAgentEnvironment.js';
import { IWorkspaceContextService } from '../../../../../platform/workspace/common/workspace.js';
import { IProductService } from '../../../../../platform/product/common/productService.js';
@@ -160,15 +160,15 @@ export class TerminalSandboxService extends Disposable implements ITerminalSandb
// If terminal sandbox settings changed, update sandbox config.
if (
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxEnabled) ||
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxEnabled) ||
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains) ||
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkAllowedDomains) ||
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains) ||
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkDeniedDomains) ||
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxLinuxFileSystem) ||
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxLinuxFileSystem) ||
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxMacFileSystem) ||
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxEnabled) ||
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkAllowedDomains) ||
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkDeniedDomains) ||
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxLinuxFileSystem) ||
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxMacFileSystem)
e?.affectsConfiguration(TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxMacFileSystem)
) {
this.setNeedsForceUpdateConfigFile();
}
@@ -600,7 +600,7 @@ export class TerminalSandboxService extends Disposable implements ITerminalSandb
if (os === OperatingSystem.Windows) {
return false;
}
return this._getSettingValue<boolean>(TerminalChatAgentToolsSettingId.AgentSandboxEnabled, TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxEnabled) ?? false;
return this._isSandboxEnabled(this._getSettingValue<TerminalChatAgentToolsSandboxEnabledValue | boolean>(TerminalChatAgentToolsSettingId.AgentSandboxEnabled, TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxEnabled) ?? TerminalChatAgentToolsSandboxEnabledValue.Off);
}
private async _resolveSrtPath(): Promise<void> {
@@ -623,13 +623,13 @@ export class TerminalSandboxService extends Disposable implements ITerminalSandb
await this._initTempDir();
}
if (this._tempDir) {
const allowedDomainsSetting = this._getSettingValue<string[]>(TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains, TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkAllowedDomains) ?? [];
const deniedDomainsSetting = this._getSettingValue<string[]>(TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains, TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkDeniedDomains) ?? [];
const allowedDomainsSetting = this._getSettingValue<string[]>(TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains, TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkAllowedDomains) ?? [];
const deniedDomainsSetting = this._getSettingValue<string[]>(TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains, TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkDeniedDomains) ?? [];
const linuxFileSystemSetting = this._os === OperatingSystem.Linux
? this._getSettingValue<{ denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }>(TerminalChatAgentToolsSettingId.AgentSandboxLinuxFileSystem, TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxLinuxFileSystem) ?? {}
? this._getSettingValue<{ denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }>(TerminalChatAgentToolsSettingId.AgentSandboxLinuxFileSystem, TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxLinuxFileSystem) ?? {}
: {};
const macFileSystemSetting = this._os === OperatingSystem.Macintosh
? this._getSettingValue<{ denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }>(TerminalChatAgentToolsSettingId.AgentSandboxMacFileSystem, TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxMacFileSystem) ?? {}
? this._getSettingValue<{ denyRead?: string[]; allowWrite?: string[]; denyWrite?: string[] }>(TerminalChatAgentToolsSettingId.AgentSandboxMacFileSystem, TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxMacFileSystem) ?? {}
: {};
const configFileUri = URI.joinPath(this._tempDir, `vscode-sandbox-settings-${this._sandboxSettingsId}.json`);
const linuxAllowWrite = this._updateAllowWritePathsWithWorkspaceFolders(linuxFileSystemSetting.allowWrite);
@@ -708,8 +708,8 @@ export class TerminalSandboxService extends Disposable implements ITerminalSandb
}
public getResolvedNetworkDomains(): ITerminalSandboxResolvedNetworkDomains {
const allowedDomains = this._getSettingValue<string[]>(TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains, TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkAllowedDomains) ?? [];
const deniedDomains = this._getSettingValue<string[]>(TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains, TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxNetworkDeniedDomains) ?? [];
const allowedDomains = this._getSettingValue<string[]>(TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains, TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkAllowedDomains) ?? [];
const deniedDomains = this._getSettingValue<string[]>(TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains, TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxNetworkDeniedDomains) ?? [];
return {
allowedDomains,
deniedDomains
@@ -738,6 +738,10 @@ export class TerminalSandboxService extends Disposable implements ITerminalSandb
}
private _isSandboxEnabled(value: TerminalChatAgentToolsSandboxEnabledValue | boolean): boolean {
return value === true || value === TerminalChatAgentToolsSandboxEnabledValue.On;
}
private _getSettingValue<T>(settingId: TerminalChatAgentToolsSettingId, deprecatedSettingId?: TerminalChatAgentToolsSettingId): T | undefined {
const setting = this._configurationService.inspect<T>(settingId);
const deprecatedSetting = deprecatedSettingId ? this._configurationService.inspect<T>(deprecatedSettingId) : undefined;

View File

@@ -16,7 +16,7 @@ import { ILogService, NullLogService } from '../../../../../../platform/log/comm
import { IProductService } from '../../../../../../platform/product/common/productService.js';
import { IRemoteAgentService } from '../../../../../services/remote/common/remoteAgentService.js';
import { URI } from '../../../../../../base/common/uri.js';
import { TerminalChatAgentToolsSettingId } from '../../common/terminalChatAgentToolsConfiguration.js';
import { TerminalChatAgentToolsSandboxEnabledValue, TerminalChatAgentToolsSettingId } from '../../common/terminalChatAgentToolsConfiguration.js';
import { Event, Emitter } from '../../../../../../base/common/event.js';
import { TestConfigurationService } from '../../../../../../platform/configuration/test/common/testConfigurationService.js';
import { VSBuffer } from '../../../../../../base/common/buffer.js';
@@ -174,7 +174,7 @@ suite('TerminalSandboxService - network domains', () => {
workspaceContextService.setWorkspaceFolders([URI.file('/workspace-one')]);
// Setup default configuration
configurationService.setUserConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxEnabled, true);
configurationService.setUserConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxEnabled, TerminalChatAgentToolsSandboxEnabledValue.On);
configurationService.setUserConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxNetworkAllowedDomains, []);
configurationService.setUserConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxNetworkDeniedDomains, []);
@@ -406,7 +406,7 @@ suite('TerminalSandboxService - network domains', () => {
if (key === TerminalChatAgentToolsSettingId.AgentSandboxEnabled) {
return {
value: undefined,
defaultValue: false,
defaultValue: TerminalChatAgentToolsSandboxEnabledValue.Off,
userValue: undefined,
userLocalValue: undefined,
userRemoteValue: undefined,
@@ -416,7 +416,7 @@ suite('TerminalSandboxService - network domains', () => {
policyValue: undefined,
} as ReturnType<typeof originalInspect<T>>;
}
if (key === TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxEnabled) {
if (key === TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxEnabled) {
return {
value: true,
defaultValue: false,
@@ -437,13 +437,13 @@ suite('TerminalSandboxService - network domains', () => {
strictEqual(await sandboxService.isEnabled(), false, 'Deprecated settings should not be used when only non-user scopes are set');
});
test('should fall back to deprecated settings in user scope', async () => {
test('should fall back to deprecated chat.agent.sandbox setting in user scope', async () => {
const originalInspect = configurationService.inspect.bind(configurationService);
configurationService.inspect = <T>(key: string) => {
if (key === TerminalChatAgentToolsSettingId.AgentSandboxEnabled) {
return {
value: undefined,
defaultValue: false,
defaultValue: TerminalChatAgentToolsSandboxEnabledValue.Off,
userValue: undefined,
userLocalValue: undefined,
userRemoteValue: undefined,
@@ -453,7 +453,7 @@ suite('TerminalSandboxService - network domains', () => {
policyValue: undefined,
} as ReturnType<typeof originalInspect<T>>;
}
if (key === TerminalChatAgentToolsSettingId.DeprecatedTerminalSandboxEnabled) {
if (key === TerminalChatAgentToolsSettingId.DeprecatedAgentSandboxEnabled) {
return {
value: true,
defaultValue: false,
@@ -471,7 +471,7 @@ suite('TerminalSandboxService - network domains', () => {
const sandboxService = store.add(instantiationService.createInstance(TerminalSandboxService));
strictEqual(await sandboxService.isEnabled(), true, 'Deprecated settings should still be respected when only the user scope is set');
strictEqual(await sandboxService.isEnabled(), true, 'Deprecated chat.agent.sandbox should still be respected when only the user scope is set');
});
test('should detect ssh style remotes as domains', async () => {

View File

@@ -42,7 +42,7 @@ import { ITerminalProfileResolverService } from '../../../../terminal/common/ter
import type { ICommandLinePresenter } from '../../browser/tools/commandLinePresenter/commandLinePresenter.js';
import { createRunInTerminalToolData, RunInTerminalTool, type IRunInTerminalInputParams } from '../../browser/tools/runInTerminalTool.js';
import { ShellIntegrationQuality } from '../../browser/toolTerminalCreator.js';
import { terminalChatAgentToolsConfiguration, TerminalChatAgentToolsSettingId } from '../../common/terminalChatAgentToolsConfiguration.js';
import { terminalChatAgentToolsConfiguration, TerminalChatAgentToolsSandboxEnabledValue, TerminalChatAgentToolsSettingId } from '../../common/terminalChatAgentToolsConfiguration.js';
import { TerminalChatService } from '../../../chat/browser/terminalChatService.js';
import type { IMarkdownString } from '../../../../../../base/common/htmlContent.js';
import { IAgentSessionsService } from '../../../../chat/browser/agentSessions/agentSessionsService.js';
@@ -642,7 +642,7 @@ suite('RunInTerminalTool', () => {
if (!confirmationMessage || typeof confirmationMessage === 'string') {
throw new Error('Expected markdown confirmation message');
}
ok(confirmationMessage.value.includes('Reason for leaving the sandbox: This command accesses evil.com, which is blocked by chat.agent.sandboxNetwork.deniedDomains.'));
ok(confirmationMessage.value.includes('Reason for leaving the sandbox: This command accesses evil.com, which is blocked by chat.agent.sandbox.deniedNetworkDomains.'));
});
test('should force confirmation for explicit unsandboxed execution requests', async () => {
@@ -2166,7 +2166,7 @@ suite('ChatAgentToolsContribution - tool registration refresh', () => {
// Enable sandbox and fire config change
sandboxEnabled = true;
configurationService.setUserConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxEnabled, true);
configurationService.setUserConfiguration(TerminalChatAgentToolsSettingId.AgentSandboxEnabled, TerminalChatAgentToolsSandboxEnabledValue.On);
configurationService.onDidChangeConfigurationEmitter.fire({
affectsConfiguration: (key: string) => key === TerminalChatAgentToolsSettingId.AgentSandboxEnabled,
affectedKeys: new Set([TerminalChatAgentToolsSettingId.AgentSandboxEnabled]),