Skip to content

fix(policy): remove unnecessary escapeRegex from pattern builders#21921

Merged
mattKorwel merged 3 commits intomainfrom
fix/policy-utils-followup-20361
Mar 11, 2026
Merged

fix(policy): remove unnecessary escapeRegex from pattern builders#21921
mattKorwel merged 3 commits intomainfrom
fix/policy-utils-followup-20361

Conversation

@spencer426
Copy link
Copy Markdown
Contributor

@spencer426 spencer426 commented Mar 10, 2026

Summary

This PR addresses post-merge review comments from PR #20361 regarding the `escapeRegex` helper and documentation within the policy utils.

Details

  • Removed the unnecessary `escapeRegex` wrapping from `buildFilePathArgsPattern` and `buildPatternArgsPattern` in `packages/core/src/policy/utils.ts`. Since `JSON.stringify` safely escapes paths and patterns into a valid JSON string, wrapping the result in `escapeRegex` again is not needed when matching against stringified tool arguments.
  • Removed an obsolete comment documenting the LLM code generation.
  • Verified that `autoAddToPolicyByDefault` in `settingsSchema.ts` was already correctly configured as `false` (opt-in).

Related Issues

Follow-up to #20361

How to Validate

  1. Review the changes in `packages/core/src/policy/utils.ts` to confirm the regex builders no longer wrap the stringified output in `escapeRegex`.
  2. All policy-related tests should still pass:
    ```bash
    npm run test -w @google/gemini-cli-core -- src/policy/
    ```

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker

@spencer426 spencer426 requested review from a team as code owners March 10, 2026 19:50
@spencer426 spencer426 force-pushed the fix/policy-utils-followup-20361 branch from 2a5f196 to f6e2be2 Compare March 10, 2026 19:50
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refines the policy management system by introducing granular control over where policy rules are saved (user vs. workspace) and automating the default selection for persistent approvals in trusted environments. It also significantly enhances the precision of generated policy rules for various tools by narrowing them to specific arguments, thereby bolstering security. The changes include refactoring regex pattern building for clarity and correctness, and introducing a new category of "sensitive tools" that require more specific policy definitions.

Highlights

  • Policy Persistence Scope: Introduced the ability to persist policy rules at either the user or workspace level, defaulting to workspace in trusted folders with enabled workspace policies.
  • Automated Policy Addition Setting: Added a new setting, security.autoAddToPolicyByDefault, which, when enabled, makes 'Allow for all future sessions' the default choice for low-risk tools in trusted workspaces.
  • Policy Rule Narrowing: Enhanced policy rules for various tools (e.g., edit, glob, grep, ls, read_file, write_file, web_fetch) by automatically generating more specific argsPatterns based on tool parameters, improving security and precision.
  • Sensitive Tool Handling: Introduced a SENSITIVE_TOOLS set and added checks to prevent broad policy updates for these tools without specific commandPrefix or argsPattern.
  • Refactored Regex Escaping: Simplified the buildArgsPatterns logic by removing redundant escapeRegex wrapping, and introduced dedicated utility functions (buildFilePathArgsPattern, buildPatternArgsPattern) for common pattern types.
Changelog
  • docs/cli/settings.md
    • Added documentation for the new security.autoAddToPolicyByDefault setting.
  • docs/reference/configuration.md
    • Included documentation for the new security.autoAddToPolicyByDefault configuration option.
  • packages/cli/src/config/settingsSchema.ts
    • Defined the schema for the new security.autoAddToPolicyByDefault setting.
  • packages/cli/src/ui/components/messages/ToolConfirmationMessage.test.tsx
    • Updated test descriptions and added a snapshot test to reflect changes in the 'Allow for all future sessions' option behavior.
  • packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx
    • Modified the 'Allow for all future sessions' label for file-specific and command-specific contexts.
    • Implemented logic to set the default selected option based on security.autoAddToPolicyByDefault and trusted folder status for low-risk tools.
    • Passed initialIndex to the RadioGroup component to control the default selection.
  • packages/cli/src/ui/components/messages/snapshots/ToolConfirmationMessage.test.tsx.snap
    • Updated the snapshot to reflect the new default selection behavior in ToolConfirmationMessage.
  • packages/core/src/agents/browser/mcpToolWrapper.ts
    • Changed getPolicyUpdateOptions from protected override to override in McpToolInvocation and TypeTextInvocation.
  • packages/core/src/config/config.ts
    • Added workspacePoliciesDir to ConfigParameters and the Config class.
    • Implemented getWorkspacePoliciesDir method to retrieve the workspace policies directory.
  • packages/core/src/config/storage.ts
    • Added getWorkspaceAutoSavedPolicyPath to retrieve the path for workspace-scoped auto-saved policies.
  • packages/core/src/confirmation-bus/types.ts
    • Added persistScope property to the UpdatePolicy interface to specify user or workspace persistence.
  • packages/core/src/policy/config.ts
    • Introduced ALWAYS_ALLOW_PRIORITY_FRACTION and ALWAYS_ALLOW_PRIORITY_OFFSET for more precise priority calculation.
    • Updated createPolicyUpdater to use persistScope for determining policy tier and to include checks for sensitive tools when updating policies.
  • packages/core/src/policy/persistence.test.ts
    • Refactored policy persistence tests to use memfs and fake timers for improved reliability and isolation.
    • Added tests for workspace-scoped persistence and handling of existing TOML files.
  • packages/core/src/policy/policy-updater.test.ts
    • Updated regex patterns in tests to use escapeRegex for consistency with the new buildArgsPatterns implementation.
  • packages/core/src/policy/utils.test.ts
    • Updated isSafeRegExp tests for invalid and long regexes, and refined tests for nested quantifiers.
    • Adjusted buildArgsPatterns tests to reflect the new escaping logic, ensuring correct JSON string literal matching.
  • packages/core/src/policy/utils.ts
    • Refactored buildArgsPatterns to directly escape the JSON literal segment, removing redundant escapeRegex wrapping.
    • Added buildFilePathArgsPattern and buildPatternArgsPattern utility functions for creating specific policy regex patterns.
  • packages/core/src/scheduler/policy.test.ts
    • Updated updatePolicy tests to include isTrustedFolder and getWorkspacePoliciesDir mocks.
    • Added tests to verify persistScope determination (workspace/user) and narrowing of edit tools with argsPattern.
  • packages/core/src/scheduler/scheduler.ts
    • Passed toolInvocation to updatePolicy to allow tool-specific policy update options.
  • packages/core/src/tools/edit.ts
    • Added resolvedPath property to EditToolInvocation to store the corrected file path.
    • Implemented getPolicyUpdateOptions to provide an argsPattern based on the file path for policy narrowing.
    • Updated EditToolInvocation and EditTool to use resolvedPath for file operations and path validation.
  • packages/core/src/tools/glob.ts
    • Implemented getPolicyUpdateOptions in GlobToolInvocation to provide an argsPattern based on the glob pattern for policy narrowing.
  • packages/core/src/tools/grep.ts
    • Implemented getPolicyUpdateOptions in GrepToolInvocation to provide an argsPattern based on the grep pattern for policy narrowing.
  • packages/core/src/tools/ls.ts
    • Implemented getPolicyUpdateOptions in LSToolInvocation to provide an argsPattern based on the directory path for policy narrowing.
  • packages/core/src/tools/mcp-tool.ts
    • Changed getPolicyUpdateOptions from protected override to override in DiscoveredMCPToolInvocation.
  • packages/core/src/tools/read-file.ts
    • Implemented getPolicyUpdateOptions in ReadFileToolInvocation to provide an argsPattern based on the file path for policy narrowing.
  • packages/core/src/tools/read-many-files.ts
    • Implemented getPolicyUpdateOptions in ReadManyFilesToolInvocation to provide an argsPattern based on the include patterns for policy narrowing.
  • packages/core/src/tools/shell.ts
    • Changed getPolicyUpdateOptions from protected override to override in ShellToolInvocation.
  • packages/core/src/tools/tool-names.ts
    • Introduced SENSITIVE_TOOLS set to categorize tools requiring extra caution for policy updates.
  • packages/core/src/tools/tools.ts
    • Added getPolicyUpdateOptions method to ToolInvocation interface and BaseToolInvocation class to allow tool-specific policy update options.
    • Added argsPattern to PolicyUpdateOptions interface.
  • packages/core/src/tools/web-fetch.ts
    • Implemented getPolicyUpdateOptions in WebFetchToolInvocation to provide an argsPattern based on the URL or prompt for policy narrowing.
  • packages/core/src/tools/write-file.ts
    • Implemented getPolicyUpdateOptions in WriteFileToolInvocation to provide an argsPattern based on the file path for policy narrowing.
  • schemas/settings.schema.json
    • Added schema definition for the new security.autoAddToPolicyByDefault setting.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 10, 2026

Size Change: -4 B (0%)

Total Size: 26.5 MB

ℹ️ View Unchanged
Filename Size Change
./bundle/gemini.js 26 MB -4 B (0%)
./bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js 221 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js 227 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js 11.5 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/types.js 132 B 0 B
./bundle/sandbox-macos-permissive-open.sb 890 B 0 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB 0 B
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB 0 B
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB 0 B
./bundle/sandbox-macos-strict-open.sb 4.82 kB 0 B
./bundle/sandbox-macos-strict-proxied.sb 5.02 kB 0 B

compressed-size-action

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new setting security.autoAddToPolicyByDefault to make "Allow for all future sessions" the default for low-risk tools in trusted workspaces. It also significantly improves security by narrowing the scope of persisted "always allow" policies for file-system and other sensitive tools to specific files or patterns, rather than the entire tool. This is a great enhancement.

However, the PR title and description are misleading as they only refer to a minor refactoring of regex pattern builders, not the main feature being introduced. Please update them to reflect the actual changes.

I've found a consistency issue in how the file paths are handled when creating these narrowed policy rules. For tools like edit_file, write_file, read_file, and ls, the raw file path from the tool parameters is used to generate the policy's argsPattern. This could lead to inconsistent and less secure policies. The path should be resolved to a canonical path relative to the workspace root before being used in a policy. I've left specific suggestions on the relevant files to address this.

Note: Security Review did not run due to the size of the PR.

I am having trouble creating individual review comments. Click here to see my feedback.

packages/core/src/tools/edit.ts (476-482)

high

To ensure policy consistency and security, the argsPattern for the policy update should be based on a canonical path relative to the workspace root, rather than the raw file_path from parameters. The this.resolvedPath is already available and should be used here, made relative to the target directory. This prevents potential issues where different but equivalent path strings (e.g., foo.txt vs ./foo.txt) would not match the same policy.

  override getPolicyUpdateOptions(
    _outcome: ToolConfirmationOutcome,
  ): PolicyUpdateOptions | undefined {
    const relativePath = makeRelative(this.resolvedPath, this.config.getTargetDir());
    return {
      argsPattern: buildFilePathArgsPattern(relativePath),
    };
  }
References
  1. File paths used in security policies must be resolved to their canonical, absolute form to prevent path traversal vulnerabilities and ensure consistent policy application. This aligns with the principle of resolving symbolic links and sanitizing user-provided paths for file system operations, and using a single robust function for path validation.

packages/core/src/tools/ls.ts (129-135)

high

The argsPattern for the ls tool should be based on a canonical, relative path to ensure policy consistency. Currently, it uses the raw dir_path parameter. I suggest resolving the path and then using that resolved path to generate a relative path for the policy pattern.

  override getPolicyUpdateOptions(
    _outcome: ToolConfirmationOutcome,
  ): PolicyUpdateOptions | undefined {
    const resolvedPath = path.resolve(
      this.config.getTargetDir(),
      this.params.dir_path,
    );
    const relativePath = makeRelative(resolvedPath, this.config.getTargetDir());
    return {
      argsPattern: buildFilePathArgsPattern(relativePath),
    };
  }
References
  1. File paths used in security policies must be resolved to their canonical, absolute form to prevent path traversal vulnerabilities and ensure consistent policy application. This aligns with the principle of resolving symbolic links and sanitizing user-provided paths for file system operations, and using a single robust function for path validation.

packages/core/src/tools/read-file.ts (94-100)

high

To improve policy security and consistency, the argsPattern should be based on the resolved, canonical path of the file, relative to the workspace root. Using the raw this.params.file_path can lead to inconsistencies. Please use this.resolvedPath to create the pattern.

  override getPolicyUpdateOptions(
    _outcome: ToolConfirmationOutcome,
  ): PolicyUpdateOptions | undefined {
    const relativePath = makeRelative(this.resolvedPath, this.config.getTargetDir());
    return {
      argsPattern: buildFilePathArgsPattern(relativePath),
    };
  }
References
  1. File paths used in security policies must be resolved to their canonical, absolute form to prevent path traversal vulnerabilities and ensure consistent policy application. This aligns with the principle of resolving symbolic links and sanitizing user-provided paths for file system operations, and using a single robust function for path validation.

packages/core/src/tools/write-file.ts (169-175)

high

For more robust and secure policies, the argsPattern should be generated from a canonical path. Please use this.resolvedPath and make it relative to the workspace root, similar to the suggestion for the edit tool. This ensures that policies are consistent regardless of how the path is specified in the tool call.

  override getPolicyUpdateOptions(
    _outcome: ToolConfirmationOutcome,
  ): PolicyUpdateOptions | undefined {
    const relativePath = makeRelative(this.resolvedPath, this.config.getTargetDir());
    return {
      argsPattern: buildFilePathArgsPattern(relativePath),
    };
  }
References
  1. File paths used in security policies must be resolved to their canonical, absolute form to prevent path traversal vulnerabilities and ensure consistent policy application. This aligns with the principle of resolving symbolic links and sanitizing user-provided paths for file system operations, and using a single robust function for path validation.

@spencer426 spencer426 requested a review from kschaab March 10, 2026 20:08
@spencer426 spencer426 enabled auto-merge March 10, 2026 20:09
@spencer426 spencer426 force-pushed the fix/policy-utils-followup-20361 branch from a885e01 to f6e2be2 Compare March 10, 2026 20:12
@gemini-cli gemini-cli bot added area/enterprise Issues related to Telemetry, Policy, Quota / Licensing 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item. labels Mar 10, 2026
@spencer426 spencer426 force-pushed the fix/policy-utils-followup-20361 branch from f6e2be2 to b24c9b8 Compare March 10, 2026 20:14
@spencer426 spencer426 added this pull request to the merge queue Mar 10, 2026
@mattKorwel mattKorwel removed this pull request from the merge queue due to a manual request Mar 10, 2026
Copy link
Copy Markdown
Collaborator

@mattKorwel mattKorwel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review and Manual Test Results

  • Intent of the PR: The author intended to remove the escapeRegex wrapping from buildFilePathArgsPattern and buildPatternArgsPattern in packages/core/src/policy/utils.ts, claiming that JSON.stringify already safely escapes paths and patterns.
  • Identified Bug: Both the static review and the manual script execution identified a critical flaw in this logic. While JSON.stringify safely escapes strings for valid JSON syntax (e.g., quotes and newlines), it does not escape Regular Expression control
    characters (such as ., +, ?, [, ], (, ), etc.).
  • Manual Execution Findings: A test script verified that without escapeRegex, any file path or pattern containing regex special characters (like src/foo[bar].ts) fails to match its literal string counterpart because the characters are interpreted as regex operators
    rather than literal characters.

The changes introduce a critical bug that compromises the security, accuracy, and core logic of the policy engine. The removal of escapeRegex breaks literal string matching for any file path or pattern containing regex special characters.

Happy to talk a bit but my review suggests that the removal here of regex escaping leaves us with a security flaw. is this known and intentional?

@mattKorwel
Copy link
Copy Markdown
Collaborator

i see this was an explicit ask i left a comment there as well #20361 (comment)

happy to be wrong, will unblock as soon as we clarify.

- Reverted the removal of `escapeRegex` around `JSON.stringify()` in `buildFilePathArgsPattern` and `buildPatternArgsPattern`. As pointed out in PR review #20361, `escapeRegex` is required to prevent Regular Expression control characters (like `.` or `+` in filenames) from acting as regex wildcards, which could allow overly broad policy matches (e.g. `foo.ts` matching `fooXts`).
- Removed the old comment documenting LLM generation.
- Added explanatory comments explaining exactly why `escapeRegex` is necessary for safety when matching literal stringified arguments.
@spencer426 spencer426 force-pushed the fix/policy-utils-followup-20361 branch from b24c9b8 to 38ca55a Compare March 10, 2026 23:03
@spencer426
Copy link
Copy Markdown
Contributor Author

@mattKorwel Thank you for the incredible catch! You are absolutely right—while JSON.stringify safely encodes strings for JSON parsing, it leaves regex control characters (like . in file extensions) unescaped. Removing escapeRegex would have turned those characters into wildcards, allowing overly broad matches (e.g., foo.ts matching fooXts).

I have updated this PR to restore the escapeRegex wrappers in buildFilePathArgsPattern and buildPatternArgsPattern. I also replaced the old LLM-generated comment with a clear explanation of why escapeRegex is critical for security here, which directly addresses the confusion from the original review.

Thanks again for the thorough manual review!

@mattKorwel mattKorwel added this pull request to the merge queue Mar 11, 2026
Merged via the queue into main with commit b87718d Mar 11, 2026
27 checks passed
@mattKorwel mattKorwel deleted the fix/policy-utils-followup-20361 branch March 11, 2026 19:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/enterprise Issues related to Telemetry, Policy, Quota / Licensing 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants