feat(cli): add native gVisor (runsc) sandboxing support (#21062)

Co-authored-by: Zheyuan <zlin252@emory.edu>
Co-authored-by: Kartik Angiras <angiraskartik@gmail.com>
This commit is contained in:
Zheyuan Lin
2026-03-05 13:39:57 -05:00
committed by GitHub
parent c7e2dbe0cf
commit 291639633f
6 changed files with 235 additions and 27 deletions

View File

@@ -573,4 +573,57 @@ describe('sandbox', () => {
});
});
});
describe('gVisor (runsc)', () => {
it('should use docker with --runtime=runsc on Linux', async () => {
vi.mocked(os.platform).mockReturnValue('linux');
const config: SandboxConfig = {
command: 'runsc',
image: 'gemini-cli-sandbox',
};
// Mock image check
interface MockProcessWithStdout extends EventEmitter {
stdout: EventEmitter;
}
const mockImageCheckProcess = new EventEmitter() as MockProcessWithStdout;
mockImageCheckProcess.stdout = new EventEmitter();
vi.mocked(spawn).mockImplementationOnce(() => {
setTimeout(() => {
mockImageCheckProcess.stdout.emit('data', Buffer.from('image-id'));
mockImageCheckProcess.emit('close', 0);
}, 1);
return mockImageCheckProcess as unknown as ReturnType<typeof spawn>;
});
// Mock docker run
const mockSpawnProcess = new EventEmitter() as unknown as ReturnType<
typeof spawn
>;
mockSpawnProcess.on = vi.fn().mockImplementation((event, cb) => {
if (event === 'close') {
setTimeout(() => cb(0), 10);
}
return mockSpawnProcess;
});
vi.mocked(spawn).mockImplementationOnce(() => mockSpawnProcess);
await start_sandbox(config, [], undefined, ['arg1']);
// Verify docker (not runsc) is called for image check
expect(spawn).toHaveBeenNthCalledWith(
1,
'docker',
expect.arrayContaining(['images', '-q', 'gemini-cli-sandbox']),
);
// Verify docker run includes --runtime=runsc
expect(spawn).toHaveBeenNthCalledWith(
2,
'docker',
expect.arrayContaining(['run', '--runtime=runsc']),
expect.objectContaining({ stdio: 'inherit' }),
);
});
});
});