Files
gemini-cli/packages/cli/src/config/policy.ts

184 lines
5.0 KiB
TypeScript

/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {
type PolicyEngineConfig,
PolicyDecision,
type PolicyRule,
ApprovalMode,
// Read-only tools
GlobTool,
GrepTool,
LSTool,
ReadFileTool,
ReadManyFilesTool,
RipGrepTool,
// Write tools
EditTool,
MemoryTool,
ShellTool,
WRITE_FILE_TOOL_NAME,
WebFetchTool,
WebSearchTool,
} from '@google/gemini-cli-core';
import type { Settings } from './settings.js';
// READ_ONLY_TOOLS is a list of built-in tools that do not modify the user's
// files or system state.
const READ_ONLY_TOOLS = new Set([
GlobTool.Name,
GrepTool.Name,
RipGrepTool.Name,
LSTool.Name,
ReadFileTool.Name,
ReadManyFilesTool.Name,
WebSearchTool.Name,
]);
// WRITE_TOOLS is a list of built-in tools that can modify the user's files or
// system state. These tools have a shouldConfirmExecute method.
// We are keeping this here for visibility and to maintain backwards compatibility
// with the existing tool permissions system. Eventually we'll remove this and
// any tool that isn't read only will require a confirmation unless altered by
// config and policy.
const WRITE_TOOLS = new Set([
EditTool.Name,
MemoryTool.Name,
ShellTool.Name,
WRITE_FILE_TOOL_NAME,
WebFetchTool.Name,
]);
export function createPolicyEngineConfig(
settings: Settings,
approvalMode: ApprovalMode,
): PolicyEngineConfig {
const rules: PolicyRule[] = [];
// Priority system for policy rules:
// - Higher priority numbers win over lower priority numbers
// - When multiple rules match, the highest priority rule is applied
// - Rules are evaluated in order of priority (highest first)
//
// Priority levels used in this configuration:
// 0: Default allow-all (YOLO mode only)
// 10: Write tools default to ASK_USER
// 50: Auto-accept read-only tools
// 85: MCP servers allowed list
// 90: MCP servers with trust=true
// 100: Explicitly allowed individual tools
// 195: Explicitly excluded MCP servers
// 200: Explicitly excluded individual tools (highest priority)
// MCP servers that are explicitly allowed in settings.mcp.allowed
// Priority: 85 (lower than trusted servers)
if (settings.mcp?.allowed) {
for (const serverName of settings.mcp.allowed) {
rules.push({
toolName: `${serverName}__*`,
decision: PolicyDecision.ALLOW,
priority: 85,
});
}
}
// MCP servers that are trusted in the settings.
// Priority: 90 (higher than general allowed servers but lower than explicit tool allows)
if (settings.mcpServers) {
for (const [serverName, serverConfig] of Object.entries(
settings.mcpServers,
)) {
if (serverConfig.trust) {
// Trust all tools from this MCP server
// Using pattern matching for MCP tool names which are formatted as "serverName__toolName"
rules.push({
toolName: `${serverName}__*`,
decision: PolicyDecision.ALLOW,
priority: 90,
});
}
}
}
// Tools that are explicitly allowed in the settings.
// Priority: 100
if (settings.tools?.allowed) {
for (const tool of settings.tools.allowed) {
rules.push({
toolName: tool,
decision: PolicyDecision.ALLOW,
priority: 100,
});
}
}
// Tools that are explicitly excluded in the settings.
// Priority: 200
if (settings.tools?.exclude) {
for (const tool of settings.tools.exclude) {
rules.push({
toolName: tool,
decision: PolicyDecision.DENY,
priority: 200,
});
}
}
// MCP servers that are explicitly excluded in settings.mcp.excluded
// Priority: 195 (high priority to block servers)
if (settings.mcp?.excluded) {
for (const serverName of settings.mcp.excluded) {
rules.push({
toolName: `${serverName}__*`,
decision: PolicyDecision.DENY,
priority: 195,
});
}
}
// If auto-accept is enabled, allow all read-only tools.
// Priority: 50
if (settings.tools?.autoAccept) {
for (const tool of READ_ONLY_TOOLS) {
rules.push({
toolName: tool,
decision: PolicyDecision.ALLOW,
priority: 50,
});
}
}
// Only add write tool rules if not in YOLO mode
// In YOLO mode, the wildcard ALLOW rule handles everything
if (approvalMode !== ApprovalMode.YOLO) {
for (const tool of WRITE_TOOLS) {
rules.push({
toolName: tool,
decision: PolicyDecision.ASK_USER,
priority: 10,
});
}
}
if (approvalMode === ApprovalMode.YOLO) {
rules.push({
decision: PolicyDecision.ALLOW,
priority: 0, // Lowest priority - catches everything not explicitly configured
});
} else if (approvalMode === ApprovalMode.AUTO_EDIT) {
rules.push({
toolName: EditTool.Name,
decision: PolicyDecision.ALLOW,
priority: 15, // Higher than write tools (10) to override ASK_USER
});
}
return {
rules,
defaultDecision: PolicyDecision.ASK_USER,
};
}