-
Notifications
You must be signed in to change notification settings - Fork 37.5k
Enabling sandboxing for terminal commands execution through copilot chat. #280236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
40882e1
0b15f7e
1084d72
c0b6751
b1976dc
a7ce30e
63cac43
caf2c45
5c21691
cd71156
762aaad
5147287
697f4f5
353d912
b634138
94f319d
a8b410c
f4e9d28
49aeae9
31ea4be
10ce464
02fec9b
22c6a80
544d616
5b01c73
dd41b1b
4742604
4adb2a6
aa3945e
1e046d4
e35e56f
2ed1d8d
46534e1
07dc6df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -20,7 +20,7 @@ import { localize } from '../../../../../../nls.js'; | |||||
| import { IConfigurationService } from '../../../../../../platform/configuration/common/configuration.js'; | ||||||
| import { IInstantiationService, type ServicesAccessor } from '../../../../../../platform/instantiation/common/instantiation.js'; | ||||||
| import { IStorageService, StorageScope, StorageTarget } from '../../../../../../platform/storage/common/storage.js'; | ||||||
| import { TerminalCapability } from '../../../../../../platform/terminal/common/capabilities/capabilities.js'; | ||||||
| import { ICommandDetectionCapability, TerminalCapability } from '../../../../../../platform/terminal/common/capabilities/capabilities.js'; | ||||||
| import { ITerminalLogService, ITerminalProfile } from '../../../../../../platform/terminal/common/terminal.js'; | ||||||
| import { IRemoteAgentService } from '../../../../../services/remote/common/remoteAgentService.js'; | ||||||
| import { TerminalToolConfirmationStorageKeys } from '../../../../chat/browser/widget/chatContentParts/toolInvocationParts/chatTerminalToolConfirmationSubPart.js'; | ||||||
|
|
@@ -45,6 +45,7 @@ import { CommandLineAutoApproveAnalyzer } from './commandLineAnalyzer/commandLin | |||||
| import { CommandLineFileWriteAnalyzer } from './commandLineAnalyzer/commandLineFileWriteAnalyzer.js'; | ||||||
| import { OutputMonitor } from './monitoring/outputMonitor.js'; | ||||||
| import { IPollingResult, OutputMonitorState } from './monitoring/types.js'; | ||||||
| import { ITerminalSandboxService } from '../../common/terminalSandboxService.js'; | ||||||
| import { chatSessionResourceToId, LocalChatSessionUri } from '../../../../chat/common/model/chatUri.js'; | ||||||
| import { URI } from '../../../../../../base/common/uri.js'; | ||||||
| import type { ICommandLineRewriter } from './commandLineRewriter/commandLineRewriter.js'; | ||||||
|
|
@@ -308,6 +309,7 @@ export class RunInTerminalTool extends Disposable implements IToolImpl { | |||||
| @ITerminalService private readonly _terminalService: ITerminalService, | ||||||
| @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService, | ||||||
| @IChatWidgetService private readonly _chatWidgetService: IChatWidgetService, | ||||||
| @ITerminalSandboxService private readonly _sandboxService: ITerminalSandboxService, | ||||||
| ) { | ||||||
| super(); | ||||||
|
|
||||||
|
|
@@ -336,6 +338,15 @@ export class RunInTerminalTool extends Disposable implements IToolImpl { | |||||
| this._storageService.remove(TerminalToolConfirmationStorageKeys.TerminalAutoApproveWarningAccepted, StorageScope.APPLICATION); | ||||||
| } | ||||||
| } | ||||||
| // If terminal sandbox settings changed, update sandbox config. | ||||||
| if ( | ||||||
| e?.affectsConfiguration(TerminalChatAgentToolsSettingId.TerminalSandboxEnabled) || | ||||||
| e?.affectsConfiguration(TerminalChatAgentToolsSettingId.TerminalSandboxNetwork) || | ||||||
| e?.affectsConfiguration(TerminalChatAgentToolsSettingId.TerminalSandboxLinuxFileSystem) || | ||||||
| e?.affectsConfiguration(TerminalChatAgentToolsSettingId.TerminalSandboxMacFileSystem) | ||||||
| ) { | ||||||
| this._sandboxService.setNeedsForceUpdateConfigFile(); | ||||||
| } | ||||||
| })); | ||||||
|
|
||||||
| // Restore terminal associations from storage | ||||||
|
|
@@ -417,6 +428,15 @@ export class RunInTerminalTool extends Disposable implements IToolImpl { | |||||
| }; | ||||||
| } | ||||||
|
|
||||||
| // If in sandbox mode, skip confirmation logic. In sandbox mode, commands are run in a restricted environment and explicit | ||||||
| // user confirmation is not required. | ||||||
| if (this._sandboxService.isEnabled()) { | ||||||
| toolSpecificData.autoApproveInfo = new MarkdownString(localize('autoApprove.sandbox', 'In sandbox mode')); | ||||||
| return { | ||||||
| toolSpecificData | ||||||
| }; | ||||||
| } | ||||||
|
|
||||||
| // Determine auto approval, this happens even when auto approve is off to that reasoning | ||||||
| // can be reviewed in the terminal channel. It also allows gauging the effective set of | ||||||
| // commands that would be auto approved if it were enabled. | ||||||
|
|
@@ -530,11 +550,11 @@ export class RunInTerminalTool extends Disposable implements IToolImpl { | |||||
|
|
||||||
| const args = invocation.parameters as IRunInTerminalInputParams; | ||||||
| this._logService.debug(`RunInTerminalTool: Invoking with options ${JSON.stringify(args)}`); | ||||||
| let toolResultMessage: string | undefined; | ||||||
| let toolResultMessage: string | IMarkdownString | undefined; | ||||||
|
|
||||||
| const chatSessionResource = invocation.context?.sessionResource ?? LocalChatSessionUri.forSession(invocation.context?.sessionId ?? 'no-chat-session'); | ||||||
| const chatSessionId = chatSessionResourceToId(chatSessionResource); | ||||||
| const command = toolSpecificData.commandLine.userEdited ?? toolSpecificData.commandLine.toolEdited ?? toolSpecificData.commandLine.original; | ||||||
| let command = toolSpecificData.commandLine.userEdited ?? toolSpecificData.commandLine.toolEdited ?? toolSpecificData.commandLine.original; | ||||||
| const didUserEditCommand = ( | ||||||
| toolSpecificData.commandLine.userEdited !== undefined && | ||||||
| toolSpecificData.commandLine.userEdited !== toolSpecificData.commandLine.original | ||||||
|
|
@@ -545,6 +565,12 @@ export class RunInTerminalTool extends Disposable implements IToolImpl { | |||||
| toolSpecificData.commandLine.toolEdited !== toolSpecificData.commandLine.original | ||||||
| ); | ||||||
|
|
||||||
| if (this._sandboxService.isEnabled()) { | ||||||
| await this._sandboxService.getSandboxConfigPath(); | ||||||
| this._logService.info(`RunInTerminalTool: Sandboxing is enabled, wrapping command with srt.`); | ||||||
| command = this._sandboxService.wrapCommand(command); | ||||||
| } | ||||||
|
|
||||||
| if (token.isCancellationRequested) { | ||||||
| throw new CancellationError(); | ||||||
| } | ||||||
|
|
@@ -688,21 +714,9 @@ export class RunInTerminalTool extends Disposable implements IToolImpl { | |||||
| } | ||||||
|
|
||||||
| try { | ||||||
| let strategy: ITerminalExecuteStrategy; | ||||||
| switch (toolTerminal.shellIntegrationQuality) { | ||||||
| case ShellIntegrationQuality.None: { | ||||||
| strategy = this._instantiationService.createInstance(NoneExecuteStrategy, toolTerminal.instance, () => toolTerminal.receivedUserInput ?? false); | ||||||
| toolResultMessage = '$(info) Enable [shell integration](https://code.visualstudio.com/docs/terminal/shell-integration) to improve command detection'; | ||||||
| break; | ||||||
| } | ||||||
| case ShellIntegrationQuality.Basic: { | ||||||
| strategy = this._instantiationService.createInstance(BasicExecuteStrategy, toolTerminal.instance, () => toolTerminal.receivedUserInput ?? false, commandDetection!); | ||||||
| break; | ||||||
| } | ||||||
| case ShellIntegrationQuality.Rich: { | ||||||
| strategy = this._instantiationService.createInstance(RichExecuteStrategy, toolTerminal.instance, commandDetection!); | ||||||
| break; | ||||||
| } | ||||||
| const strategy: ITerminalExecuteStrategy = this._getExecuteStrategy(toolTerminal.shellIntegrationQuality, toolTerminal, commandDetection!); | ||||||
| if (toolTerminal.shellIntegrationQuality === ShellIntegrationQuality.None) { | ||||||
| toolResultMessage = '$(info) Enable [shell integration](https://code.visualstudio.com/docs/terminal/shell-integration) to improve command detection'; | ||||||
| } | ||||||
| this._logService.debug(`RunInTerminalTool: Using \`${strategy.type}\` execute strategy for command \`${command}\``); | ||||||
| store.add(strategy.onDidCreateStartMarker(startMarker => { | ||||||
|
|
@@ -762,7 +776,6 @@ export class RunInTerminalTool extends Disposable implements IToolImpl { | |||||
| } | ||||||
| terminalResult = resultArr.join('\n\n'); | ||||||
| } | ||||||
|
|
||||||
| } catch (e) { | ||||||
| // Handle timeout case - get output collected so far and return it | ||||||
| if (didTimeout && e instanceof CancellationError) { | ||||||
|
|
@@ -1006,6 +1019,21 @@ export class RunInTerminalTool extends Disposable implements IToolImpl { | |||||
| } | ||||||
| } | ||||||
|
||||||
| } | |
| } |
Uh oh!
There was an error while loading. Please reload this page.