feat(windows-sandbox): address final async review findings and fix eslint

This commit is contained in:
mkorwel
2026-03-18 12:07:17 -07:00
parent f08fad9b87
commit 2431d75250
3 changed files with 72 additions and 50 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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,
);
}
}
}