mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-28 22:14:52 -07:00
feat(core): populate sandbox forbidden paths with project ignore file contents (#24038)
This commit is contained in:
@@ -38,7 +38,7 @@ describe('WindowsSandboxManager', () => {
|
||||
manager = new WindowsSandboxManager({
|
||||
workspace: testCwd,
|
||||
modeConfig: { readonly: false, allowOverrides: true },
|
||||
forbiddenPaths: [],
|
||||
forbiddenPaths: async () => [],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -107,7 +107,7 @@ describe('WindowsSandboxManager', () => {
|
||||
const planManager = new WindowsSandboxManager({
|
||||
workspace: testCwd,
|
||||
modeConfig: { readonly: true, allowOverrides: false },
|
||||
forbiddenPaths: [],
|
||||
forbiddenPaths: async () => [],
|
||||
});
|
||||
const req: SandboxRequest = {
|
||||
command: 'curl',
|
||||
@@ -139,7 +139,7 @@ describe('WindowsSandboxManager', () => {
|
||||
workspace: testCwd,
|
||||
modeConfig: { allowOverrides: true, network: false },
|
||||
policyManager: mockPolicyManager,
|
||||
forbiddenPaths: [],
|
||||
forbiddenPaths: async () => [],
|
||||
});
|
||||
|
||||
const req: SandboxRequest = {
|
||||
@@ -369,7 +369,7 @@ describe('WindowsSandboxManager', () => {
|
||||
|
||||
const managerWithForbidden = new WindowsSandboxManager({
|
||||
workspace: testCwd,
|
||||
forbiddenPaths: [missingPath],
|
||||
forbiddenPaths: async () => [missingPath],
|
||||
});
|
||||
|
||||
const req: SandboxRequest = {
|
||||
@@ -397,7 +397,7 @@ describe('WindowsSandboxManager', () => {
|
||||
try {
|
||||
const managerWithForbidden = new WindowsSandboxManager({
|
||||
workspace: testCwd,
|
||||
forbiddenPaths: [forbiddenPath],
|
||||
forbiddenPaths: async () => [forbiddenPath],
|
||||
});
|
||||
|
||||
const req: SandboxRequest = {
|
||||
@@ -427,7 +427,7 @@ describe('WindowsSandboxManager', () => {
|
||||
try {
|
||||
const managerWithForbidden = new WindowsSandboxManager({
|
||||
workspace: testCwd,
|
||||
forbiddenPaths: [conflictPath],
|
||||
forbiddenPaths: async () => [conflictPath],
|
||||
});
|
||||
|
||||
const req: SandboxRequest = {
|
||||
@@ -458,12 +458,9 @@ describe('WindowsSandboxManager', () => {
|
||||
call[1][0] === path.resolve(conflictPath),
|
||||
);
|
||||
|
||||
// Both should have been called
|
||||
expect(allowCallIndex).toBeGreaterThan(-1);
|
||||
// Conflict should have been filtered out of allow calls
|
||||
expect(allowCallIndex).toBe(-1);
|
||||
expect(denyCallIndex).toBeGreaterThan(-1);
|
||||
|
||||
// Verify order: explicitly denying must happen after the explicit allow
|
||||
expect(allowCallIndex).toBeLessThan(denyCallIndex);
|
||||
} finally {
|
||||
fs.rmSync(conflictPath, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
tryRealpath,
|
||||
type SandboxPermissions,
|
||||
type ParsedSandboxDenial,
|
||||
resolveSandboxPaths,
|
||||
} from '../../services/sandboxManager.js';
|
||||
import type { ShellExecutionResult } from '../../services/shellExecutionService.js';
|
||||
import {
|
||||
@@ -288,14 +289,16 @@ export class WindowsSandboxManager implements SandboxManager {
|
||||
await this.grantLowIntegrityAccess(this.options.workspace);
|
||||
}
|
||||
|
||||
const { allowed: allowedPaths, forbidden: forbiddenPaths } =
|
||||
await resolveSandboxPaths(this.options, req);
|
||||
|
||||
// Grant "Low Mandatory Level" access to includeDirectories.
|
||||
const includeDirs = sanitizePaths(this.options.includeDirectories) || [];
|
||||
const includeDirs = sanitizePaths(this.options.includeDirectories);
|
||||
for (const includeDir of includeDirs) {
|
||||
await this.grantLowIntegrityAccess(includeDir);
|
||||
}
|
||||
|
||||
// Grant "Low Mandatory Level" read/write access to allowedPaths.
|
||||
const allowedPaths = sanitizePaths(req.policy?.allowedPaths) || [];
|
||||
for (const allowedPath of allowedPaths) {
|
||||
const resolved = await tryRealpath(allowedPath);
|
||||
if (!fs.existsSync(resolved)) {
|
||||
@@ -308,8 +311,9 @@ export class WindowsSandboxManager implements SandboxManager {
|
||||
}
|
||||
|
||||
// Grant "Low Mandatory Level" write access to additional permissions write paths.
|
||||
const additionalWritePaths =
|
||||
sanitizePaths(mergedAdditional.fileSystem?.write) || [];
|
||||
const additionalWritePaths = sanitizePaths(
|
||||
mergedAdditional.fileSystem?.write,
|
||||
);
|
||||
for (const writePath of additionalWritePaths) {
|
||||
const resolved = await tryRealpath(writePath);
|
||||
if (!fs.existsSync(resolved)) {
|
||||
@@ -358,7 +362,6 @@ export class WindowsSandboxManager implements SandboxManager {
|
||||
// is restricted to avoid host corruption. External commands rely on
|
||||
// Low Integrity read/write restrictions, while internal commands
|
||||
// use the manifest for enforcement.
|
||||
const forbiddenPaths = sanitizePaths(this.options.forbiddenPaths) || [];
|
||||
for (const forbiddenPath of forbiddenPaths) {
|
||||
try {
|
||||
await this.denyLowIntegrityAccess(forbiddenPath);
|
||||
|
||||
Reference in New Issue
Block a user