mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-28 05:55:17 -07:00
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:
@@ -86,6 +86,35 @@ describe('WindowsSandboxManager', () => {
|
||||
expect(result.args[0]).toBe('1');
|
||||
});
|
||||
|
||||
it('should NOT whitelist drive roots in YOLO mode', async () => {
|
||||
manager = new WindowsSandboxManager({
|
||||
workspace: testCwd,
|
||||
modeConfig: { readonly: false, allowOverrides: true, yolo: true },
|
||||
forbiddenPaths: async () => [],
|
||||
});
|
||||
|
||||
const req: SandboxRequest = {
|
||||
command: 'whoami',
|
||||
args: [],
|
||||
cwd: testCwd,
|
||||
env: {},
|
||||
};
|
||||
|
||||
await manager.prepareCommand(req);
|
||||
|
||||
// Verify spawnAsync was called for icacls
|
||||
const icaclsCalls = vi
|
||||
.mocked(spawnAsync)
|
||||
.mock.calls.filter((call) => call[0] === 'icacls');
|
||||
|
||||
// Should NOT have called icacls for C:\, D:\, etc.
|
||||
const driveRootCalls = icaclsCalls.filter(
|
||||
(call) =>
|
||||
typeof call[1]?.[0] === 'string' && /^[A-Z]:\\$/.test(call[1][0]),
|
||||
);
|
||||
expect(driveRootCalls).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should handle network access from additionalPermissions', async () => {
|
||||
const req: SandboxRequest = {
|
||||
command: 'whoami',
|
||||
|
||||
@@ -72,6 +72,10 @@ export class WindowsSandboxManager implements SandboxManager {
|
||||
return parseWindowsSandboxDenials(result);
|
||||
}
|
||||
|
||||
getWorkspace(): string {
|
||||
return this.options.workspace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures a file or directory exists.
|
||||
*/
|
||||
@@ -240,6 +244,8 @@ export class WindowsSandboxManager implements SandboxManager {
|
||||
];
|
||||
}
|
||||
|
||||
const isYolo = this.options.modeConfig?.yolo ?? false;
|
||||
|
||||
// Fetch persistent approvals for this command
|
||||
const commandName = await getCommandName(command, args);
|
||||
const persistentPermissions = allowOverrides
|
||||
@@ -259,6 +265,7 @@ export class WindowsSandboxManager implements SandboxManager {
|
||||
],
|
||||
},
|
||||
network:
|
||||
isYolo ||
|
||||
persistentPermissions?.network ||
|
||||
req.policy?.additionalPermissions?.network ||
|
||||
false,
|
||||
@@ -301,7 +308,9 @@ export class WindowsSandboxManager implements SandboxManager {
|
||||
// Grant "Low Mandatory Level" read/write access to allowedPaths.
|
||||
for (const allowedPath of allowedPaths) {
|
||||
const resolved = await tryRealpath(allowedPath);
|
||||
if (!fs.existsSync(resolved)) {
|
||||
try {
|
||||
await fs.promises.access(resolved, fs.constants.F_OK);
|
||||
} catch {
|
||||
throw new Error(
|
||||
`Sandbox request rejected: Allowed path does not exist: ${resolved}. ` +
|
||||
'On Windows, granular sandbox access can only be granted to existing paths to avoid broad parent directory permissions.',
|
||||
@@ -316,7 +325,9 @@ export class WindowsSandboxManager implements SandboxManager {
|
||||
);
|
||||
for (const writePath of additionalWritePaths) {
|
||||
const resolved = await tryRealpath(writePath);
|
||||
if (!fs.existsSync(resolved)) {
|
||||
try {
|
||||
await fs.promises.access(resolved, fs.constants.F_OK);
|
||||
} catch {
|
||||
throw new Error(
|
||||
`Sandbox request rejected: Additional write path does not exist: ${resolved}. ` +
|
||||
'On Windows, granular sandbox access can only be granted to existing paths to avoid broad parent directory permissions.',
|
||||
|
||||
Reference in New Issue
Block a user