fix(core): enhance sandbox usability and fix build error (#24460)

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
Gal Zahavi
2026-04-01 16:51:06 -07:00
committed by GitHub
parent ca78a0f177
commit 13ccc16457
22 changed files with 1285 additions and 53 deletions
@@ -57,6 +57,7 @@ export interface SandboxModeConfig {
network?: boolean;
approvedTools?: string[];
allowOverrides?: boolean;
yolo?: boolean;
}
/**
@@ -140,6 +141,11 @@ export interface SandboxManager {
* Parses the output of a command to detect sandbox denials.
*/
parseDenials(result: ShellExecutionResult): ParsedSandboxDenial | undefined;
/**
* Returns the primary workspace directory for this sandbox.
*/
getWorkspace(): string;
}
/**
@@ -238,6 +244,8 @@ export async function findSecretFiles(
* through while applying environment sanitization.
*/
export class NoopSandboxManager implements SandboxManager {
constructor(private options?: GlobalSandboxOptions) {}
/**
* Prepares a command by sanitizing the environment and passing through
* the original program and arguments.
@@ -271,12 +279,18 @@ export class NoopSandboxManager implements SandboxManager {
parseDenials(): undefined {
return undefined;
}
getWorkspace(): string {
return this.options?.workspace ?? process.cwd();
}
}
/**
* A SandboxManager implementation that just runs locally (no sandboxing yet).
*/
export class LocalSandboxManager implements SandboxManager {
constructor(private options?: GlobalSandboxOptions) {}
async prepareCommand(_req: SandboxRequest): Promise<SandboxedCommand> {
throw new Error('Tool sandboxing is not yet implemented.');
}
@@ -292,6 +306,10 @@ export class LocalSandboxManager implements SandboxManager {
parseDenials(): undefined {
return undefined;
}
getWorkspace(): string {
return this.options?.workspace ?? process.cwd();
}
}
/**
@@ -24,10 +24,6 @@ export function createSandboxManager(
options: GlobalSandboxOptions,
approvalMode?: string,
): SandboxManager {
if (approvalMode === 'yolo') {
return new NoopSandboxManager();
}
if (!options.modeConfig && options.policyManager && approvalMode) {
options.modeConfig = options.policyManager.getModeConfig(approvalMode);
}
@@ -40,8 +36,8 @@ export function createSandboxManager(
} else if (os.platform() === 'darwin') {
return new MacOsSandboxManager(options);
}
return new LocalSandboxManager();
return new LocalSandboxManager(options);
}
return new NoopSandboxManager();
return new NoopSandboxManager(options);
}
@@ -47,6 +47,10 @@ class MockSandboxManager implements SandboxManager {
parseDenials(): undefined {
return undefined;
}
getWorkspace(): string {
return '/workspace';
}
}
describe('SandboxedFileSystemService', () => {
@@ -1915,6 +1915,7 @@ describe('ShellExecutionService environment variables', () => {
isKnownSafeCommand: vi.fn().mockReturnValue(false),
isDangerousCommand: vi.fn().mockReturnValue(false),
parseDenials: vi.fn().mockReturnValue(undefined),
getWorkspace: vi.fn().mockReturnValue('/workspace'),
};
const configWithSandbox: ShellExecutionConfig = {