Skip to content

feat(policy): support auto-add to policy by default and scoped persistence#20361

Merged
spencer426 merged 9 commits intomainfrom
fixes/17148_add_policy
Mar 10, 2026
Merged

feat(policy): support auto-add to policy by default and scoped persistence#20361
spencer426 merged 9 commits intomainfrom
fixes/17148_add_policy

Conversation

@spencer426
Copy link
Contributor

@spencer426 spencer426 commented Feb 25, 2026

Summary

This PR implements the "auto-add to policy by default" feature (#17148) as an opt-in setting, streamlining the tool approval process in trusted workspaces while enhancing security through rule narrowing for edit/exec tools and workspace-scoped persistence.

Details

  • Opt-in Auto-add: The new setting security.autoAddToPolicyByDefault (default: false) allows users to make "Allow for all future sessions" the default choice for tools in trusted workspaces.
  • Rule Narrowing & Scoped Persistence:
    • Approvals for edit tools (e.g., write_file) and exec tools are now strictly narrowed to the specific file or root command using relative paths.
    • Policy persistence now prefers a workspace-local policy file (.gemini/policies/auto-saved.toml) when the folder is trusted.
  • Improved UI Clarity: UI labels for permanent approvals have been updated to be more specific (e.g., "Allow for this file in all future sessions").
  • Core Refactors & Robustness:
    • Refactored regex pattern builders in utils.ts to use safe JSON.stringify logic, avoiding brittle slicing.
    • Restored and unified priority calculation logic using getAlwaysAllowPriorityFraction and ALWAYS_ALLOW_PRIORITY_FRACTION.
    • Improved test stability using advanceTimersByTimeAsync and escapeRegex for assertions.
    • Fixed a regression where EditTool path correction was interfering with policy matching.
  • Experimental Sandbox Support: (Note: This PR currently includes experimental support for LXC and gVisor/runsc sandboxing as part of the broader tool isolation improvements).

Related Issues

Closes #17148

How to Validate

  1. Enable Opt-in: Set "security.autoAddToPolicyByDefault": true and "security.enablePermanentToolApproval": true in your settings.
  2. Trusted Folder: Open the CLI in a trusted directory.
  3. Trigger Edit: Perform an operation that triggers edit or write_file.
  4. Observe Default: Verify that "Allow for this file in all future sessions" is the default selected option.
  5. Verify Persistence: Select the option and verify that a narrowed rule is saved to .gemini/policies/auto-saved.toml (if workspace policies are enabled) or the global auto-saved policy.
  6. Narrowing Check: Verify the saved rule uses a relative path and correctly constrains future calls.

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:
    • Linux
      • npm run

@spencer426 spencer426 requested review from a team as code owners February 25, 2026 22:46
@gemini-code-assist

This comment was marked as outdated.

gemini-code-assist[bot]

This comment was marked as outdated.

@github-actions
Copy link

github-actions bot commented Feb 25, 2026

Size Change: +6.46 kB (+0.02%)

Total Size: 26.2 MB

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

compressed-size-action

@gemini-cli gemini-cli bot added area/enterprise Issues related to Telemetry, Policy, Quota / Licensing 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item. labels Feb 25, 2026
@spencer426 spencer426 force-pushed the fixes/17148_add_policy branch 2 times, most recently from 2bbda31 to 07bea4f Compare February 26, 2026 23:55
@spencer426 spencer426 force-pushed the fixes/17148_add_policy branch 5 times, most recently from 5c02895 to 1dbe1de Compare February 27, 2026 09:01
@jacob314 jacob314 requested a review from galz10 February 27, 2026 15:44
galz10

This comment was marked as resolved.

@spencer426 spencer426 force-pushed the fixes/17148_add_policy branch from 9095519 to f904a4b Compare March 2, 2026 15:58
@spencer426 spencer426 changed the title feat(security): support auto-add to policy by default with safeguards feat(security): implement auto-add to policy with smart specificity and safeguards Mar 2, 2026
@gemini-cli

This comment was marked as outdated.

@gemini-cli gemini-cli bot closed this Mar 2, 2026
@spencer426 spencer426 reopened this Mar 2, 2026
@spencer426 spencer426 linked an issue Mar 2, 2026 that may be closed by this pull request
@spencer426 spencer426 force-pushed the fixes/17148_add_policy branch 2 times, most recently from 99b4d9d to 72a9ad3 Compare March 4, 2026 04:16
@spencer426 spencer426 changed the title feat(security): implement auto-add to policy with smart specificity and safeguards feat(policy): support auto-add to policy by default and scoped persistence Mar 4, 2026
Copy link
Contributor

@jacob314 jacob314 left a comment

Choose a reason for hiding this comment

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

LGTM once we back out the functionality making approve all the default which needs to be an opt in only setting or removed.

@spencer426 spencer426 force-pushed the fixes/17148_add_policy branch 2 times, most recently from 18b6f51 to c70ca89 Compare March 9, 2026 21:58
- Set autoAddToPolicyByDefault to false (opt-in only) per Jacob's request.
- Refactored regex pattern builders in utils.ts to be safer and avoid brittle slicing.
- Updated documentation and JSON schema to reflect the new default value.
- Restored and cleaned up priority constants and helpers in config.ts.
- Improved test robustness by using escapeRegex in assertions.
- Narrowed permanent approval label for file edits to be more specific.
@spencer426 spencer426 force-pushed the fixes/17148_add_policy branch from c70ca89 to 45d9c5c Compare March 9, 2026 22:18
@spencer426 spencer426 force-pushed the fixes/17148_add_policy branch from 60bfdc0 to 014a13a Compare March 10, 2026 14:50
@spencer426 spencer426 requested a review from jacob314 March 10, 2026 16:36
// and wraps it in double quotes. We simply prepend the key name and escape
// the entire sequence for Regex matching without any slicing.
const encodedPath = JSON.stringify(filePath);
return escapeRegex(`"file_path":${encodedPath}`);
Copy link
Contributor

Choose a reason for hiding this comment

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

why are we calling escapeRegex here and line 116? That seems unneeded.

Copy link
Collaborator

Choose a reason for hiding this comment

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

gemini tells me without this we are insecure? i blocked the follow on pr just to verify...


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.

Final Recommendation
Reject the PR.

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.

The assessment recommends leaving a comment on the PR explaining the difference between JSON escaping and Regex escaping, and requesting that the author restore the escapeRegex calls around JSON.stringify.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry my mistake. I think the correct order of operations is
JSON.stringify(escapeRegex(filePath))
Calling escapeRegex after the JSON.stringify doesn't make sense but calling it before is reasonable if the pattern we are trying to match is the filePath as an escaped regexp.

Copy link
Contributor

@jacob314 jacob314 left a comment

Choose a reason for hiding this comment

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

lgtm

@spencer426 spencer426 added this pull request to the merge queue Mar 10, 2026
Merged via the queue into main with commit a220874 Mar 10, 2026
26 of 27 checks passed
@spencer426 spencer426 deleted the fixes/17148_add_policy branch March 10, 2026 17:14
spencer426 added a commit that referenced this pull request Mar 10, 2026
- 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.
JaisalJain pushed a commit to JaisalJain/gemini-cli that referenced this pull request Mar 11, 2026
kunal-10-cloud pushed a commit to kunal-10-cloud/gemini-cli that referenced this pull request Mar 12, 2026
liamhelmer pushed a commit to badal-io/gemini-cli that referenced this pull request Mar 12, 2026
yashodipmore pushed a commit to yashodipmore/geemi-cli that referenced this pull request Mar 21, 2026
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.

Support auto-add to policy by default

4 participants