Skip to content
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
40882e1
Enable sandboxing for terminal commands
dileepyavan Dec 1, 2025
0b15f7e
removing unused types
dileepyavan Dec 4, 2025
1084d72
code review comments update
dileepyavan Jan 6, 2026
c0b6751
main merge
dileepyavan Jan 7, 2026
b1976dc
refactored the code and added utility for sandboxing
dileepyavan Jan 10, 2026
a7ce30e
refactored the code and added utility for sandboxing
dileepyavan Jan 10, 2026
63cac43
refactored the code and added utility for sandboxing
dileepyavan Jan 10, 2026
caf2c45
fixing build error
dileepyavan Jan 12, 2026
5c21691
review suggestions
dileepyavan Jan 14, 2026
cd71156
review suggestions
dileepyavan Jan 14, 2026
762aaad
changes for retry
dileepyavan Jan 14, 2026
5147287
changes for retry
dileepyavan Jan 14, 2026
697f4f5
Update src/vs/workbench/contrib/terminalContrib/chatAgentTools/common…
dileepyavan Jan 14, 2026
353d912
Update src/vs/workbench/contrib/terminalContrib/chatAgentTools/browse…
dileepyavan Jan 14, 2026
b634138
Update src/vs/workbench/contrib/terminalContrib/chatAgentTools/common…
dileepyavan Jan 14, 2026
94f319d
Update src/vs/workbench/contrib/terminalContrib/chatAgentTools/browse…
dileepyavan Jan 14, 2026
a8b410c
Update src/vs/workbench/contrib/terminalContrib/chatAgentTools/browse…
dileepyavan Jan 14, 2026
f4e9d28
merging from main
dileepyavan Jan 15, 2026
49aeae9
updating anthropic sandbox runtime to 0.0.23
dileepyavan Jan 15, 2026
31ea4be
fixing tests for runInTerminalTool
dileepyavan Jan 15, 2026
10ce464
refactoring changes
dileepyavan Jan 15, 2026
02fec9b
review changes
dileepyavan Jan 15, 2026
22c6a80
review changes
dileepyavan Jan 15, 2026
544d616
review changes
dileepyavan Jan 15, 2026
5b01c73
review changes
dileepyavan Jan 15, 2026
dd41b1b
review changes
dileepyavan Jan 15, 2026
4742604
review changes
dileepyavan Jan 15, 2026
4adb2a6
review changes
dileepyavan Jan 16, 2026
aa3945e
update to sandboxservice
dileepyavan Jan 16, 2026
1e046d4
update to sandboxservice
dileepyavan Jan 16, 2026
e35e56f
update to sandboxservice
dileepyavan Jan 16, 2026
2ed1d8d
removing extra line
dileepyavan Jan 16, 2026
46534e1
formatting PR suggested by copilot
dileepyavan Jan 16, 2026
07dc6df
files location change suggested for review
dileepyavan Jan 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 76 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"update-build-ts-version": "npm install -D typescript@next && npm install -D @typescript/native-preview && (cd build && npm run typecheck)"
},
"dependencies": {
"@anthropic-ai/sandbox-runtime": "0.0.23",
"@microsoft/1ds-core-js": "^3.2.13",
"@microsoft/1ds-post-js": "^3.2.13",
"@parcel/watcher": "^2.5.4",
Expand Down Expand Up @@ -240,4 +241,4 @@
"optionalDependencies": {
"windows-foreground-love": "0.5.0"
}
}
}
24 changes: 24 additions & 0 deletions src/vs/platform/terminal/common/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@ import type { IAction } from '../../../base/common/actions.js';
import type { IDisposable } from '../../../base/common/lifecycle.js';
import type { SingleOrMany } from '../../../base/common/types.js';

/**
* Local type definition for sandbox runtime configuration to avoid importing external package
* in the common layer. The actual type should match @anthropic-ai/sandbox-runtime.
*/
export interface ITerminalSandboxRuntimeConfig {
network?: {
allowedDomains?: string[];
deniedDomains?: string[];
};
filesystem?: {
denyRead?: string[];
allowWrite?: string[];
denyWrite?: string[];
};
}

export const enum TerminalSettingPrefix {
AutomationProfile = 'terminal.integrated.automationProfile.',
DefaultProfile = 'terminal.integrated.defaultProfile.',
Expand Down Expand Up @@ -673,6 +689,11 @@ export interface IShellLaunchConfig {
shellIntegrationNonce?: string;
}

export interface ITerminalSandboxSettings extends ITerminalSandboxRuntimeConfig {
enabled?: boolean;
}


export interface ITerminalTabAction {
id: string;
label: string;
Expand Down Expand Up @@ -730,6 +751,7 @@ export interface ITerminalProcessOptions {
environmentVariableCollections: ISerializableEnvironmentVariableCollections | undefined;
workspaceFolder: IWorkspaceFolder | undefined;
isScreenReaderOptimized: boolean;
sandboxSettings?: ITerminalSandboxRuntimeConfig;
}

export interface ITerminalEnvironment {
Expand Down Expand Up @@ -921,6 +943,8 @@ export interface ITerminalProfile {
overrideName?: boolean;
color?: string;
icon?: ThemeIcon | URI | { light: URI; dark: URI };
sandboxed?: boolean;
sandboxSettings?: ITerminalSandboxRuntimeConfig;
}

export interface ITerminalDimensionsOverride extends Readonly<ITerminalDimensions> {
Expand Down
130 changes: 130 additions & 0 deletions src/vs/workbench/contrib/terminal/common/terminalSandboxService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { isNative, OperatingSystem, OS } from '../../../../base/common/platform.js';
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
import { ITerminalSandboxSettings } from '../../../../platform/terminal/common/terminal.js';
import { ILogService } from '../../../../platform/log/common/log.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
import { dirname, join } from '../../../../base/common/path.js';
import { FileAccess } from '../../../../base/common/network.js';
import { URI } from '../../../../base/common/uri.js';
import { IFileService } from '../../../../platform/files/common/files.js';
import { VSBuffer } from '../../../../base/common/buffer.js';
import { joinPath } from '../../../../base/common/resources.js';
import { generateUuid } from '../../../../base/common/uuid.js';
import { IEnvironmentService } from '../../../../platform/environment/common/environment.js';
import { TerminalContribSettingId } from '../terminalContribExports.js';
import { IRemoteAgentService } from '../../../services/remote/common/remoteAgentService.js';

export const ITerminalSandboxService = createDecorator<ITerminalSandboxService>('terminalSandboxService');

export interface ITerminalSandboxService {
readonly _serviceBrand: undefined;
isEnabled(): boolean;
wrapCommand(command: string): string;
getSandboxConfigPath(forceRefresh?: boolean): Promise<string | undefined>;
getTempDir(): URI | undefined;
setNeedsForceUpdateConfigFile(): void;
}

export class TerminalSandboxService implements ITerminalSandboxService {
readonly _serviceBrand: undefined;
private _srtPath: string;
private _sandboxConfigPath: string | undefined;
private _needsForceUpdateConfigFile = true;
private _tempDir: URI | undefined;
private _sandboxSettingsId: string | undefined;
private _os: OperatingSystem = OS;


constructor(
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IFileService private readonly _fileService: IFileService,
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
@ILogService private readonly _logService: ILogService,
@IRemoteAgentService private readonly _remoteAgentService: IRemoteAgentService,
) {
const appRoot = dirname(FileAccess.asFileUri('').fsPath);
this._srtPath = join(appRoot, 'node_modules', '.bin', 'srt');
this._sandboxSettingsId = generateUuid();
this._initTempDir();
this._remoteAgentService.getEnvironment().then(remoteEnv => this._os = remoteEnv?.os ?? OS);
}

public isEnabled(): boolean {
if (this._os === OperatingSystem.Windows) {
return false;
}
return this._configurationService.getValue<boolean>(TerminalContribSettingId.TerminalSandboxEnabled);
}

public wrapCommand(command: string): string {
if (!this._sandboxConfigPath || !this._tempDir) {
throw new Error('Sandbox config path or temp dir not initialized');
}
return `"${this._srtPath}" TMPDIR=${this._tempDir.fsPath} --settings "${this._sandboxConfigPath}" "${command}"`;
}

public getTempDir(): URI | undefined {
return this._tempDir;
}

public setNeedsForceUpdateConfigFile(): void {
this._needsForceUpdateConfigFile = true;
}

public async getSandboxConfigPath(forceRefresh: boolean = false): Promise<string | undefined> {
if (!this._sandboxConfigPath || forceRefresh || this._needsForceUpdateConfigFile) {
this._sandboxConfigPath = await this._createSandboxConfig();
this._needsForceUpdateConfigFile = false;
}
return this._sandboxConfigPath;
}

private async _createSandboxConfig(): Promise<string | undefined> {

if (this.isEnabled() && !this._tempDir) {
this._initTempDir();
}
if (this._tempDir) {
const networkSetting = this._configurationService.getValue<ITerminalSandboxSettings['network']>(TerminalContribSettingId.TerminalSandboxNetwork) ?? {};
const linuxFileSystemSetting = this._os === OperatingSystem.Linux
? this._configurationService.getValue<ITerminalSandboxSettings['filesystem']>(TerminalContribSettingId.TerminalSandboxLinuxFileSystem) ?? {}
: {};
const macFileSystemSetting = this._os === OperatingSystem.Macintosh
? this._configurationService.getValue<ITerminalSandboxSettings['filesystem']>(TerminalContribSettingId.TerminalSandboxMacFileSystem) ?? {}
: {};
const configFileUri = joinPath(this._tempDir, `vscode-sandbox-settings-${this._sandboxSettingsId}.json`);
const sandboxSettings = {
network: {
allowedDomains: networkSetting.allowedDomains ?? [],
deniedDomains: networkSetting.deniedDomains ?? []
},
filesystem: {
denyRead: this._os === OperatingSystem.Macintosh ? macFileSystemSetting.denyRead : linuxFileSystemSetting.denyRead,
allowWrite: this._os === OperatingSystem.Macintosh ? macFileSystemSetting.allowWrite : linuxFileSystemSetting.allowWrite,
denyWrite: this._os === OperatingSystem.Macintosh ? macFileSystemSetting.denyWrite : linuxFileSystemSetting.denyWrite,
}
};
this._sandboxConfigPath = configFileUri.fsPath;
await this._fileService.createFile(configFileUri, VSBuffer.fromString(JSON.stringify(sandboxSettings, null, '\t')), { overwrite: true });
return this._sandboxConfigPath;
}
return undefined;
}

private _initTempDir(): void {
if (this.isEnabled() && isNative) {
this._needsForceUpdateConfigFile = true;
const environmentService = this._environmentService as IEnvironmentService & { tmpDir?: URI };
this._tempDir = environmentService.tmpDir;
if (!this._tempDir) {
this._logService.warn('TerminalSandboxService: Cannot create sandbox settings file because no tmpDir is available in this environment');
return;
}
}
}
}
6 changes: 5 additions & 1 deletion src/vs/workbench/contrib/terminal/terminalContribExports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ export const enum TerminalContribSettingId {
AutoApprove = TerminalChatAgentToolsSettingId.AutoApprove,
EnableAutoApprove = TerminalChatAgentToolsSettingId.EnableAutoApprove,
ShellIntegrationTimeout = TerminalChatAgentToolsSettingId.ShellIntegrationTimeout,
OutputLocation = TerminalChatAgentToolsSettingId.OutputLocation
OutputLocation = TerminalChatAgentToolsSettingId.OutputLocation,
TerminalSandboxEnabled = TerminalChatAgentToolsSettingId.TerminalSandboxEnabled,
TerminalSandboxNetwork = TerminalChatAgentToolsSettingId.TerminalSandboxNetwork,
TerminalSandboxLinuxFileSystem = TerminalChatAgentToolsSettingId.TerminalSandboxLinuxFileSystem,
TerminalSandboxMacFileSystem = TerminalChatAgentToolsSettingId.TerminalSandboxMacFileSystem,
}

// HACK: Export some context key strings from `terminalContrib/` that are depended upon elsewhere.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ import { RunInTerminalTool, createRunInTerminalToolData } from './tools/runInTer
import { CreateAndRunTaskTool, CreateAndRunTaskToolData } from './tools/task/createAndRunTaskTool.js';
import { GetTaskOutputTool, GetTaskOutputToolData } from './tools/task/getTaskOutputTool.js';
import { RunTaskTool, RunTaskToolData } from './tools/task/runTaskTool.js';
import { InstantiationType, registerSingleton } from '../../../../../platform/instantiation/common/extensions.js';
import { ITerminalSandboxService, TerminalSandboxService } from '../../../terminal/common/terminalSandboxService.js';

// #region Services

registerSingleton(ITerminalSandboxService, TerminalSandboxService, InstantiationType.Delayed);

// #endregion Services

class ShellIntegrationTimeoutMigrationContribution extends Disposable implements IWorkbenchContribution {
static readonly ID = 'terminal.shellIntegrationTimeoutMigration';
Expand Down
Loading
Loading