How Roo Code Enforces Tool Group Restrictions and File Patterns in Its Mode System

Roo Code uses a mode‑centric permission model that cross‑references mode configurations with tool group memberships, alias resolution, and runtime overrides to enforce strict access controls, while file‑pattern limits are applied per‑call via ripgrep glob arguments.

The Roo Code mode system, as implemented in the RooCodeInc/Roo‑Code repository, provides a granular sandbox for AI assistant capabilities. By defining which tool groups each mode may access and enforcing file pattern restrictions at the tool‑execution layer, the system ensures that agents operate within their intended boundaries.

The Mode-Centric Permission Architecture

Roo Code’s enforcement mechanism rests on a validation pipeline that translates high‑level mode configurations into concrete runtime permissions. The process involves canonical group definitions, alias resolution, and multi‑layered filtering before any tool reaches the LLM context.

Canonical Tool Groups and Schema Definitions

The foundation of the permission model is the toolGroups array defined in the shared types package:

export const toolGroups = ["read", "edit", "command", "mcp", "modes"] as const

This declaration in packages/types/src/tool.ts L07‑L10 establishes the valid group namespaces that modes can request. Each group represents a logical collection of native tools—for example, the edit group contains file‑modifying utilities, while read covers inspection tools.

Expanding Mode Groups to Concrete Tool Lists

When a user selects a mode, the system expands the mode’s configured groups into an explicit list of tool names via getToolsForMode(modeConfig.groups). This expansion occurs in src/core/prompts/tools/filter‑tools‑for‑mode.ts L45‑L46, where group entries (which may be simple strings or tuples with options) are resolved into the full set of tools implied by those groups.

Validating Tools Against Mode Permissions

The core enforcement logic resides in isToolAllowedForMode, which validates whether a specific tool belongs to one of the mode’s enabled groups. During the filtering process in filter‑tools‑for‑mode.ts L48‑L60, the system:

  1. Iterates over allToolsForMode.
  2. Resolves any aliases to canonical names.
  3. Calls isToolAllowedForMode (implemented in src/core/tools/validateToolUse.ts) to verify the tool’s group membership against the mode’s whitelist.

If a tool does not belong to an allowed group, it is excluded from the final set.

Alias Resolution Before Validation

To maintain backward compatibility without breaking security boundaries, Roo Code resolves legacy tool names before validation. The ALIAS_TO_CANONICAL map—built from TOOL_ALIASES at module load time in L14‑L22—translates aliases like search_and_replace to their canonical equivalents (e.g., edit).

During the construction of allowedToolNames in L96‑L99, resolveToolAlias ensures that even when an LLM requests a tool by its legacy name, the permission check evaluates against the canonical group membership.

Runtime Overrides and Final Whitelist Construction

After establishing the base tool set, filterNativeToolsForMode applies several conditional filters to produce the final runtime whitelist:

  • Model customizations: applyModelToolCustomization adds or removes tools based on the specific LLM’s capabilities.
  • Feature flags: Code like allowedToolNames.delete("codebase_search") in L71‑L77 removes tools when prerequisite services (such as the code‑index) are unavailable.
  • User settings: Blocks checking settings?.disabledTools?.length in L94‑L100 prune tools explicitly disabled by the user.
  • MCP availability: Lines L04‑L07 verify that MCP tools are only included when the MCP hub is active.

The result is a Set<string> of allowedToolNames that represents the definitive boundary of what the assistant may invoke.

File Pattern Enforcement in Search Operations

Beyond group‑level restrictions, Roo Code enforces file‑pattern limits at the individual tool‑call level, particularly for the search_files utility.

The search_files Tool Interface

The search_files tool accepts an optional file_pattern parameter that constrains the search scope:

interface SearchFilesParams {
  path: string
  regex: string
  file_pattern?: string | null   // optional glob pattern
}

In src/core/tools/SearchFilesTool.ts L58‑L60, the implementation forwards this parameter unchanged to the underlying search service:

const results = await regexSearchFiles(
  task.cwd,
  absolutePath,
  regex,
  filePattern,                 // forwarded to ripgrep
  task.rooIgnoreController
);

Ripgrep Glob Filtering

The actual enforcement occurs in src/services/ripgrep/index.ts. When filePattern is provided, the service converts it into a --glob argument for the rg command:

// Inside ripgrep service, lines L21‑L23 and L157‑L158
const rgArgs = ["--glob", filePattern, ...];

This ensures that even if a mode grants access to search_files, the operation is physically restricted to files matching the glob pattern (for example, **/*.ts limits results to TypeScript files).

Complete Runtime Flow

The enforcement pipeline operates sequentially during mode activation:

  1. Mode selection: The user selects a mode (or a custom mode is inferred), triggering filterNativeToolsForMode with the current mode slug, custom definitions, experiment flags, and service states.
  2. Group expansion: Mode groups are expanded to tool lists via getToolsForMode.
  3. Alias resolution: Tool names are normalized using ALIAS_TO_CANONICAL.
  4. Permission validation: isToolAllowedForMode filters the list to only those tools belonging to enabled groups.
  5. Override application: Model customizations, disabled tool lists, and feature flags prune the set further.
  6. Tool exposure: The resulting array of OpenAI.Chat.ChatCompletionTool objects is injected into the LLM context.
  7. Per‑call enforcement: When the assistant invokes search_files, the optional file_pattern is validated and passed to ripgrep, which applies the --glob filter at the filesystem level.

Key Implementation Files

Summary

  • Roo Code enforces tool access through a mode‑centric permission model that validates every tool against configurable group memberships.
  • The filterNativeToolsForMode function in src/core/prompts/tools/filter‑tools‑for‑mode.ts constructs the runtime whitelist by expanding mode groups, resolving aliases, and applying model‑specific and user‑specific overrides.
  • Alias resolution occurs before validation, ensuring legacy tool names are mapped to canonical groups without bypassing restrictions.
  • File‑pattern restrictions are enforced at the execution layer; the search_files tool forwards glob patterns to ripgrep, which filters results via --glob arguments.
  • The entire pipeline ensures that even if an LLM attempts to invoke a restricted tool or access excluded files, the operation is blocked by the mode configuration or the filesystem search boundary.

Frequently Asked Questions

How does filterNativeToolsForMode determine which tools are available?

The function first calls getToolsForMode(modeConfig.groups) to expand the mode’s groups into concrete tool names (L45‑L46). It then iterates over these candidates, uses isToolAllowedForMode to verify group membership (L48‑L60), and applies subsequent filters for disabled tools, model customizations, and MCP availability (L71‑L100). The result is a deduplicated array of tools the LLM is permitted to call.

What happens when a tool alias is used in a mode‑restricted context?

Before validation, the system checks the ALIAS_TO_CANONICAL map (constructed from TOOL_ALIASES at L14‑L22) to resolve the alias to its canonical name. For example, search_and_replace resolves to edit. The permission check then evaluates against the canonical group, ensuring aliases cannot bypass group restrictions while preserving backward compatibility (L96‑L99).

How does Roo Code handle file pattern restrictions in search_files?

The search_files tool accepts an optional file_pattern parameter that is forwarded directly to regexSearchFiles in src/core/tools/SearchFilesTool.ts (L58‑L60). The ripgrep service in src/services/ripgrep/index.ts converts this into a --glob argument for the underlying rg command (L21‑L23), filtering the search to matching paths only.

Can model‑specific customizations override mode‑based tool restrictions?

Yes. After the mode‑based whitelist is constructed, filterNativeToolsForMode invokes applyModelToolCustomization to add or remove tools based on the specific LLM’s capabilities. However, this occurs after the mode group validation, meaning model customizations can only further restrict or supplement the base set; they cannot grant access to tools outside the mode’s allowed groups unless explicitly intended by the broader override logic.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →