mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-15 06:12:50 -07:00
feat(sandbox): grant default write access to ~/.gemini/tmp
Updates sandbox managers for macOS, Linux, and Windows to grant full read/write access to the Gemini temporary directory (~/.gemini/tmp) by default. This ensures that sandboxed tools can reliably use this directory for temporary storage across all platforms.
This commit is contained in:
@@ -256,6 +256,7 @@ export class LinuxSandboxManager implements SandboxManager {
|
||||
includeDirectories: this.options.includeDirectories || [],
|
||||
maskFilePath: this.getMaskFilePath(),
|
||||
isWriteCommand: req.command === '__write',
|
||||
geminiTmpPath: join(os.homedir(), '.gemini', 'tmp'),
|
||||
});
|
||||
|
||||
const bpfPath = getSeccompBpfPath();
|
||||
|
||||
@@ -33,6 +33,7 @@ export interface BwrapArgsOptions {
|
||||
includeDirectories: string[];
|
||||
maskFilePath: string;
|
||||
isWriteCommand: boolean;
|
||||
geminiTmpPath?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,6 +64,15 @@ export async function buildBwrapArgs(
|
||||
'/tmp',
|
||||
);
|
||||
|
||||
// Allow read/write access to the Gemini temporary directory if provided
|
||||
if (options.geminiTmpPath) {
|
||||
const geminiTmp = tryRealpath(options.geminiTmpPath);
|
||||
bwrapArgs.push('--bind-try', options.geminiTmpPath, options.geminiTmpPath);
|
||||
if (geminiTmp !== options.geminiTmpPath) {
|
||||
bwrapArgs.push('--bind-try', geminiTmp, geminiTmp);
|
||||
}
|
||||
}
|
||||
|
||||
const workspacePath = tryRealpath(options.workspace);
|
||||
|
||||
const bindFlag = options.workspaceWrite ? '--bind-try' : '--ro-bind-try';
|
||||
|
||||
@@ -144,6 +144,7 @@ export class MacOsSandboxManager implements SandboxManager {
|
||||
networkAccess: mergedAdditional.network,
|
||||
workspaceWrite,
|
||||
additionalPermissions: mergedAdditional,
|
||||
geminiTmpPath: path.join(os.homedir(), '.gemini', 'tmp'),
|
||||
});
|
||||
|
||||
const tempFile = this.writeProfileToTempFile(sandboxArgs);
|
||||
|
||||
@@ -34,6 +34,8 @@ export interface SeatbeltArgsOptions {
|
||||
additionalPermissions?: SandboxPermissions;
|
||||
/** Whether to allow write access to the workspace. */
|
||||
workspaceWrite?: boolean;
|
||||
/** The path to the Gemini temporary directory (~/.gemini/tmp). */
|
||||
geminiTmpPath?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,6 +63,15 @@ export function buildSeatbeltProfile(options: SeatbeltArgsOptions): string {
|
||||
const tmpPath = tryRealpath(os.tmpdir());
|
||||
profile += `(allow file-read* file-write* (subpath "${escapeSchemeString(tmpPath)}"))\n`;
|
||||
|
||||
// Allow read/write access to the Gemini temporary directory if provided
|
||||
if (options.geminiTmpPath) {
|
||||
const geminiTmp = tryRealpath(options.geminiTmpPath);
|
||||
profile += `(allow file-read* file-write* (subpath "${escapeSchemeString(options.geminiTmpPath)}"))\n`;
|
||||
if (geminiTmp !== options.geminiTmpPath) {
|
||||
profile += `(allow file-read* file-write* (subpath "${escapeSchemeString(geminiTmp)}"))\n`;
|
||||
}
|
||||
}
|
||||
|
||||
// Add explicit deny rules for governance files in the workspace.
|
||||
// These are added after the workspace allow rule to ensure they take precedence
|
||||
// (Seatbelt evaluates rules in order, later rules win for same path).
|
||||
|
||||
@@ -222,7 +222,25 @@ export class WindowsSandboxManager implements SandboxManager {
|
||||
|
||||
// Native commands __read and __write are passed directly to GeminiSandbox.exe
|
||||
|
||||
const isApproved = allowOverrides
|
||||
? await isStrictlyApproved(
|
||||
command,
|
||||
args,
|
||||
this.options.modeConfig?.approvedTools,
|
||||
)
|
||||
: false;
|
||||
|
||||
const isYolo = this.options.modeConfig?.yolo ?? false;
|
||||
const workspaceWrite = !isReadonlyMode || isApproved || isYolo;
|
||||
|
||||
if (workspaceWrite) {
|
||||
await this.grantLowIntegrityAccess(this.options.workspace);
|
||||
}
|
||||
|
||||
// Grant write access to the Gemini temporary directory
|
||||
await this.grantLowIntegrityAccess(
|
||||
path.join(os.homedir(), '.gemini', 'tmp'),
|
||||
);
|
||||
|
||||
// Fetch persistent approvals for this command
|
||||
const commandName = await getCommandName(command, args);
|
||||
@@ -259,21 +277,6 @@ export class WindowsSandboxManager implements SandboxManager {
|
||||
this.options.modeConfig?.network ?? req.policy?.networkAccess ?? false;
|
||||
const networkAccess = defaultNetwork || mergedAdditional.network;
|
||||
|
||||
// 1. Handle filesystem permissions for Low Integrity
|
||||
// Grant "Low Mandatory Level" write access to the workspace.
|
||||
// If not in readonly mode OR it's a strictly approved pipeline, allow workspace writes
|
||||
const isApproved = allowOverrides
|
||||
? await isStrictlyApproved(
|
||||
command,
|
||||
args,
|
||||
this.options.modeConfig?.approvedTools,
|
||||
)
|
||||
: false;
|
||||
|
||||
if (!isReadonlyMode || isApproved) {
|
||||
await this.grantLowIntegrityAccess(this.options.workspace);
|
||||
}
|
||||
|
||||
const { allowed: allowedPaths, forbidden: forbiddenPaths } =
|
||||
await resolveSandboxPaths(this.options, req);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user