Download packages/core/src/policy/sandboxPolicyManager.ts from SaylorTwift/gemini-cli: direct link, hf CLI and curl.
- Browser
- Download file 7.42 kB
-
https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/core/src/policy/sandboxPolicyManager.ts
- Command line
-
hf download hf://SaylorTwift/gemini-cli/packages/core/src/policy/sandboxPolicyManager.ts
-
curl -L -o sandboxPolicyManager.ts https://huggingface.co/SaylorTwift/gemini-cli/resolve/main/packages/core/src/policy/sandboxPolicyManager.ts
7.42 kB
| /** | |
| * @license | |
| * Copyright 2026 Google LLC | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| import fs from 'node:fs'; | |
| import path from 'node:path'; | |
| import os from 'node:os'; | |
| import toml from '@iarna/toml'; | |
| import { z } from 'zod'; | |
| import { fileURLToPath } from 'node:url'; | |
| import { debugLogger } from '../utils/debugLogger.js'; | |
| import { type SandboxPermissions } from '../services/sandboxManager.js'; | |
| import { deduplicateAbsolutePaths } from '../utils/paths.js'; | |
| import { normalizeCommand } from '../utils/shell-utils.js'; | |
| export const SandboxModeConfigSchema = z.object({ | |
| network: z.boolean(), | |
| readonly: z.boolean(), | |
| approvedTools: z.array(z.string()), | |
| allowOverrides: z.boolean().optional(), | |
| yolo: z.boolean().optional(), | |
| }); | |
| export const PersistentCommandConfigSchema = z.object({ | |
| allowed_paths: z.array(z.string()).optional(), | |
| allow_network: z.boolean().optional(), | |
| }); | |
| export const SandboxTomlSchema = z.object({ | |
| modes: z.object({ | |
| plan: SandboxModeConfigSchema, | |
| default: SandboxModeConfigSchema, | |
| accepting_edits: SandboxModeConfigSchema, | |
| }), | |
| commands: z.record(z.string(), PersistentCommandConfigSchema).default({}), | |
| }); | |
| export type SandboxModeConfig = z.infer<typeof SandboxModeConfigSchema>; | |
| export type PersistentCommandConfig = z.infer< | |
| typeof PersistentCommandConfigSchema | |
| >; | |
| export type SandboxTomlSchemaType = z.infer<typeof SandboxTomlSchema>; | |
| export class SandboxPolicyManager { | |
| private static _DEFAULT_CONFIG: SandboxTomlSchemaType | null = null; | |
| private static get DEFAULT_CONFIG(): SandboxTomlSchemaType { | |
| if (!SandboxPolicyManager._DEFAULT_CONFIG) { | |
| const __filename = fileURLToPath(import.meta.url); | |
| const __dirname = path.dirname(__filename); | |
| const defaultPath = path.join( | |
| __dirname, | |
| 'policies', | |
| 'sandbox-default.toml', | |
| ); | |
| try { | |
| const content = fs.readFileSync(defaultPath, 'utf8'); | |
| if (typeof content !== 'string') { | |
| SandboxPolicyManager._DEFAULT_CONFIG = { | |
| modes: { | |
| plan: { | |
| network: false, | |
| readonly: true, | |
| approvedTools: [], | |
| allowOverrides: true, | |
| }, | |
| default: { | |
| network: false, | |
| readonly: false, | |
| approvedTools: [], | |
| allowOverrides: true, | |
| }, | |
| accepting_edits: { | |
| network: false, | |
| readonly: false, | |
| approvedTools: ['sed', 'grep', 'awk', 'perl', 'cat', 'echo'], | |
| allowOverrides: true, | |
| }, | |
| }, | |
| commands: {}, | |
| }; | |
| return SandboxPolicyManager._DEFAULT_CONFIG; | |
| } | |
| SandboxPolicyManager._DEFAULT_CONFIG = SandboxTomlSchema.parse( | |
| toml.parse(content), | |
| ); | |
| } catch (e) { | |
| debugLogger.error(`Failed to parse default sandbox policy: ${e}`); | |
| throw new Error(`Failed to parse default sandbox policy: ${e}`); | |
| } | |
| } | |
| return SandboxPolicyManager._DEFAULT_CONFIG; | |
| } | |
| private config: SandboxTomlSchemaType; | |
| private readonly configPath: string; | |
| private sessionApprovals: Record<string, SandboxPermissions> = {}; | |
| constructor(customConfigPath?: string) { | |
| this.configPath = | |
| customConfigPath ?? | |
| path.join(os.homedir(), '.gemini', 'policies', 'sandbox.toml'); | |
| this.config = this.loadConfig(); | |
| } | |
| private isProtectedKey(key: string): boolean { | |
| return key === '__proto__' || key === 'constructor' || key === 'prototype'; | |
| } | |
| private loadConfig(): SandboxTomlSchemaType { | |
| if (!fs.existsSync(this.configPath)) { | |
| return SandboxPolicyManager.DEFAULT_CONFIG; | |
| } | |
| try { | |
| const content = fs.readFileSync(this.configPath, 'utf8'); | |
| return SandboxTomlSchema.parse(toml.parse(content)); | |
| } catch (e) { | |
| debugLogger.error(`Failed to parse sandbox.toml: ${e}`); | |
| return SandboxPolicyManager.DEFAULT_CONFIG; | |
| } | |
| } | |
| private saveConfig(): void { | |
| try { | |
| const dir = path.dirname(this.configPath); | |
| if (!fs.existsSync(dir)) { | |
| fs.mkdirSync(dir, { recursive: true }); | |
| } | |
| // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion | |
| const content = toml.stringify(this.config as unknown as toml.JsonMap); | |
| fs.writeFileSync(this.configPath, content); | |
| } catch (e) { | |
| debugLogger.error(`Failed to save sandbox.toml: ${e}`); | |
| } | |
| } | |
| getModeConfig( | |
| mode: 'plan' | 'accepting_edits' | 'default' | 'yolo' | string, | |
| ): SandboxModeConfig { | |
| if (mode === 'yolo') { | |
| return { | |
| network: true, | |
| readonly: false, | |
| approvedTools: [], | |
| allowOverrides: true, | |
| yolo: true, | |
| }; | |
| } | |
| if (mode === 'plan') return this.config.modes.plan; | |
| if (mode === 'accepting_edits' || mode === 'autoEdit') | |
| return this.config.modes.accepting_edits; | |
| if (mode === 'default') return this.config.modes.default; | |
| // Default fallback | |
| return this.config.modes.default ?? this.config.modes.plan; | |
| } | |
| getCommandPermissions(commandName: string): SandboxPermissions { | |
| const normalized = normalizeCommand(commandName); | |
| if (this.isProtectedKey(normalized)) { | |
| return { | |
| fileSystem: { read: [], write: [] }, | |
| network: false, | |
| }; | |
| } | |
| const persistent = this.config.commands[normalized]; | |
| const session = this.sessionApprovals[normalized]; | |
| return { | |
| fileSystem: { | |
| read: [ | |
| ...(persistent?.allowed_paths ?? []), | |
| ...(session?.fileSystem?.read ?? []), | |
| ], | |
| write: [ | |
| ...(persistent?.allowed_paths ?? []), | |
| ...(session?.fileSystem?.write ?? []), | |
| ], | |
| }, | |
| network: persistent?.allow_network || session?.network || false, | |
| }; | |
| } | |
| addSessionApproval( | |
| commandName: string, | |
| permissions: SandboxPermissions, | |
| ): void { | |
| const normalized = normalizeCommand(commandName); | |
| if (this.isProtectedKey(normalized)) { | |
| return; | |
| } | |
| const existing = this.sessionApprovals[normalized] || { | |
| fileSystem: { read: [], write: [] }, | |
| network: false, | |
| }; | |
| this.sessionApprovals[normalized] = { | |
| fileSystem: { | |
| read: deduplicateAbsolutePaths([ | |
| ...(existing.fileSystem?.read ?? []), | |
| ...(permissions.fileSystem?.read ?? []), | |
| ]), | |
| write: deduplicateAbsolutePaths([ | |
| ...(existing.fileSystem?.write ?? []), | |
| ...(permissions.fileSystem?.write ?? []), | |
| ]), | |
| }, | |
| network: existing.network || permissions.network || false, | |
| }; | |
| } | |
| addPersistentApproval( | |
| commandName: string, | |
| permissions: SandboxPermissions, | |
| ): void { | |
| const normalized = normalizeCommand(commandName); | |
| if (this.isProtectedKey(normalized)) { | |
| return; | |
| } | |
| const existing = this.config.commands[normalized] || { | |
| allowed_paths: [], | |
| allow_network: false, | |
| }; | |
| const newPathsArray: string[] = [ | |
| ...(existing.allowed_paths ?? []), | |
| ...(permissions.fileSystem?.read ?? []), | |
| ...(permissions.fileSystem?.write ?? []), | |
| ]; | |
| const newPaths = new Set(deduplicateAbsolutePaths(newPathsArray)); | |
| this.config.commands[normalized] = { | |
| allowed_paths: Array.from(newPaths), | |
| allow_network: existing.allow_network || permissions.network || false, | |
| }; | |
| this.saveConfig(); | |
| } | |
| } | |