Implementation of sandbox "Write-Protected" Governance Files (#23139)

Co-authored-by: Abhi <43648792+abhipatel12@users.noreply.github.com>
This commit is contained in:
David Pierce
2026-03-24 04:04:17 +00:00
committed by GitHub
parent a833d350a4
commit 37c8de3c06
7 changed files with 365 additions and 51 deletions
@@ -12,6 +12,7 @@ import {
type SandboxManager,
type SandboxRequest,
type SandboxedCommand,
GOVERNANCE_FILES,
type GlobalSandboxOptions,
sanitizePaths,
} from './sandboxManager.js';
@@ -39,6 +40,28 @@ export class WindowsSandboxManager implements SandboxManager {
this.helperPath = path.resolve(__dirname, 'scripts', 'GeminiSandbox.exe');
}
/**
* Ensures a file or directory exists.
*/
private touch(filePath: string, isDirectory: boolean): void {
try {
// If it exists (even as a broken symlink), do nothing
if (fs.lstatSync(filePath)) return;
} catch {
// Ignore ENOENT
}
if (isDirectory) {
fs.mkdirSync(filePath, { recursive: true });
} else {
const dir = path.dirname(filePath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
fs.closeSync(fs.openSync(filePath, 'a'));
}
}
private async ensureInitialized(): Promise<void> {
if (this.initialized) return;
if (os.platform() !== 'win32') {
@@ -164,7 +187,28 @@ export class WindowsSandboxManager implements SandboxManager {
// TODO: handle forbidden paths
// 2. Construct the helper command
// 2. Protected governance files
// These must exist on the host before running the sandbox to prevent
// the sandboxed process from creating them with Low integrity.
// By being created as Medium integrity, they are write-protected from Low processes.
for (const file of GOVERNANCE_FILES) {
const filePath = path.join(this.options.workspace, file.path);
this.touch(filePath, file.isDirectory);
// We resolve real paths to ensure protection for both the symlink and its target.
try {
const realPath = fs.realpathSync(filePath);
if (realPath !== filePath) {
// If it's a symlink, the target is already implicitly protected
// if it's outside the Low integrity workspace (likely Medium).
// If it's inside, we ensure it's not accidentally Low.
}
} catch {
// Ignore realpath errors
}
}
// 3. Construct the helper command
// GeminiSandbox.exe <network:0|1> <cwd> <command> [args...]
const program = this.helperPath;