diff --git a/packages/core/src/services/sandboxedFileSystemService.test.ts b/packages/core/src/services/sandboxedFileSystemService.test.ts index d18fcce962..973c642436 100644 --- a/packages/core/src/services/sandboxedFileSystemService.test.ts +++ b/packages/core/src/services/sandboxedFileSystemService.test.ts @@ -11,8 +11,9 @@ import type { SandboxRequest, SandboxedCommand, } from './sandboxManager.js'; -import { spawn } from 'node:child_process'; +import { spawn, type ChildProcess } from 'node:child_process'; import { EventEmitter } from 'node:events'; +import type { Writable } from 'node:stream'; vi.mock('node:child_process', () => ({ spawn: vi.fn(), @@ -40,10 +41,11 @@ describe('SandboxedFileSystemService', () => { }); it('should read a file through the sandbox', async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const mockChild = new EventEmitter() as any; - mockChild.stdout = new EventEmitter(); - mockChild.stderr = new EventEmitter(); + const mockChild = new EventEmitter() as unknown as ChildProcess; + Object.assign(mockChild, { + stdout: new EventEmitter(), + stderr: new EventEmitter(), + }); vi.mocked(spawn).mockReturnValue(mockChild); @@ -65,13 +67,14 @@ describe('SandboxedFileSystemService', () => { }); it('should write a file through the sandbox', async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const mockChild = new EventEmitter() as any; - mockChild.stdin = { - write: vi.fn(), - end: vi.fn(), - }; - mockChild.stderr = new EventEmitter(); + const mockChild = new EventEmitter() as unknown as ChildProcess; + Object.assign(mockChild, { + stdin: { + write: vi.fn(), + end: vi.fn(), + } as unknown as Writable, + stderr: new EventEmitter(), + }); vi.mocked(spawn).mockReturnValue(mockChild); @@ -92,10 +95,11 @@ describe('SandboxedFileSystemService', () => { }); it('should reject if sandbox command fails', async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const mockChild = new EventEmitter() as any; - mockChild.stdout = new EventEmitter(); - mockChild.stderr = new EventEmitter(); + const mockChild = new EventEmitter() as unknown as ChildProcess; + Object.assign(mockChild, { + stdout: new EventEmitter(), + stderr: new EventEmitter(), + }); vi.mocked(spawn).mockReturnValue(mockChild); diff --git a/packages/core/src/services/scripts/GeminiSandbox.cs b/packages/core/src/services/scripts/GeminiSandbox.cs index b56e2772d6..78bd54144d 100644 --- a/packages/core/src/services/scripts/GeminiSandbox.cs +++ b/packages/core/src/services/scripts/GeminiSandbox.cs @@ -1,3 +1,9 @@ +/** + * @license + * Copyright 2026 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + using System; using System.Runtime.InteropServices; using System.Collections.Generic; diff --git a/packages/core/src/services/windowsSandboxManager.ts b/packages/core/src/services/windowsSandboxManager.ts index df69c95a92..f16181e4d4 100644 --- a/packages/core/src/services/windowsSandboxManager.ts +++ b/packages/core/src/services/windowsSandboxManager.ts @@ -17,6 +17,7 @@ import { sanitizeEnvironment, type EnvironmentSanitizationConfig, } from './environmentSanitization.js'; +import { debugLogger } from '../utils/debugLogger.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -44,42 +45,49 @@ export class WindowsSandboxManager implements SandboxManager { return; } - if (!fs.existsSync(this.helperPath)) { - // If the exe doesn't exist, we try to compile it from the .cs file - const sourcePath = this.helperPath.replace(/\.exe$/, '.cs'); - if (fs.existsSync(sourcePath)) { - const systemRoot = process.env['SystemRoot'] || 'C:\\Windows'; - const cscPaths = [ - 'csc.exe', // Try in PATH first - path.join( - systemRoot, - 'Microsoft.NET', - 'Framework64', - 'v4.0.30319', - 'csc.exe', - ), - path.join( - systemRoot, - 'Microsoft.NET', - 'Framework', - 'v4.0.30319', - 'csc.exe', - ), - ]; + try { + if (!fs.existsSync(this.helperPath)) { + // If the exe doesn't exist, we try to compile it from the .cs file + const sourcePath = this.helperPath.replace(/\.exe$/, '.cs'); + if (fs.existsSync(sourcePath)) { + const systemRoot = process.env['SystemRoot'] || 'C:\\Windows'; + const cscPaths = [ + 'csc.exe', // Try in PATH first + path.join( + systemRoot, + 'Microsoft.NET', + 'Framework64', + 'v4.0.30319', + 'csc.exe', + ), + path.join( + systemRoot, + 'Microsoft.NET', + 'Framework', + 'v4.0.30319', + 'csc.exe', + ), + ]; - for (const csc of cscPaths) { - const result = spawnSync( - csc, - ['/out:' + this.helperPath, sourcePath], - { - stdio: 'ignore', - }, - ); - if (result.status === 0) { - break; + for (const csc of cscPaths) { + const result = spawnSync( + csc, + ['/out:' + this.helperPath, sourcePath], + { + stdio: 'ignore', + }, + ); + if (result.status === 0) { + break; + } } } } + } catch (e) { + debugLogger.log( + 'WindowsSandboxManager: Failed to initialize sandbox helper:', + e, + ); } this.initialized = true; @@ -171,8 +179,12 @@ export class WindowsSandboxManager implements SandboxManager { if (result.status === 0) { this.lowIntegrityCache.add(resolvedPath); } - } catch (_e) { - // Best effort + } catch (e) { + debugLogger.log( + 'WindowsSandboxManager: icacls failed for', + resolvedPath, + e, + ); } } }