Skip to content

Policy Engine rules ignored in non-interactive mode with --approval-mode auto_edit #20469

Closed

Description

@EricRahm

What happened?

When running gemini-cli in non-interactive mode (using the -p or --prompt flag), the Policy Engine ignores "allow" decisions for specific tools, even when a high-priority rule is explicitly defined. This is because the CLI's configuration layer applies a hardcoded "extra exclude" list to tools like run_shell_command in auto_edit mode when interaction is disabled, which prevents the tool from even being registered, regardless of the Policy Engine's rules.

What did you expect to happen?

The Policy Engine should be the source of truth for tool availability. If a policy explicitly allows a tool (or a specific command prefix), it should be available for execution even in non-interactive mode.

Client information

Client Information - **CLI Version:** 0.30.0-nightly.20260210.a2174751d - **Git Commit:** ac454bc - **OS:** Linux - **Approval Mode:** auto_edit - **Interface:** Non-interactive (-p flag)

Login information

API key

Anything else we need to know?

Steps to Reproduce

  1. Create a policy file named repro-policy.toml:
    [[rule]]
    toolName = "run_shell_command"
    commandPrefix = "cargo"
    decision = "allow"
    priority = 100
  2. Create a fake responses file repro-responses.jsonl:
    {"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"I will check cargo options."},{"functionCall":{"args":{"command":"cargo --help"},"name":"run_shell_command"}}]},"finishReason":"STOP"}]}]}
  3. Run the CLI in non-interactive mode with the policy and fake responses:
    npm run start --
      --model gemini-2.0-flash
      --fake-responses ./repro-responses.jsonl
      --policy ./repro-policy.toml
      --approval-mode auto_edit
      -p "describe the options to the cargo command"
  4. Observe the error:
    Error executing tool run_shell_command: Tool "run_shell_command" not found. Did you mean one of: "get_sheet_content", "read_document", "grep_search"?
    

Further Research

Behavior Across Approval Modes (Non-interactive)

Testing with a custom allow policy for run_shell_command shows inconsistent behavior across modes:

Mode Result Reasoning
yolo Success Explicitly bypasses hardcoded excludes.
auto_edit Failure Hardcoded as excluded in packages/cli/src/config/config.ts.
default Failure Part of defaultExcludes in non-interactive mode.
plan Failure Part of defaultExcludes in non-interactive mode.

Root Cause Analysis

It appears that the Config class in packages/core/src/config/config.ts treats hardcoded exclusions and Policy Engine exclusions as a simple union. There is no mechanism for the Policy Engine to "re-allow" a tool that has been statically excluded by the CLI.

When ToolRegistry initializes, it calls config.getExcludeTools(). The implementation is as follows:

// packages/core/src/config/config.ts
getExcludeTools(...): Set<string> | undefined {
  // 1. Start with hardcoded excludes from settings/CLI flags
  const excludeToolsSet = new Set([...(this.excludeTools ?? [])]);

  // 2. Add exclusions from extensions ...

  // 3. Add exclusions from the Policy Engine
  const policyExclusions = this.policyEngine.getExcludedTools(toolMetadata, allToolNames);
  for (const tool of policyExclusions) {
    excludeToolsSet.add(tool);
  }

  return excludeToolsSet;
}

Because run_shell_command is added to this.excludeTools by the CLI's configuration logic (in packages/cli/src/config/config.ts), it is present in the set before the Policy Engine is consulted. Even if the Policy Engine has a high-priority allow rule, it simply results in the tool not being added to policyExclusions. It cannot remove the tool from the already-populated excludeToolsSet.

As a result, the tool is never registered in the ToolRegistry, leading to the "Tool not found" error during execution.

Workarounds

I can use --allowed-tools, but that's deprecated. It'd just be nice if this worked before we remove that.

Activity

  1. added
    status/need-triageIssues that need to be triaged by the triage automation.
    area/enterpriseIssues related to Telemetry, Policy, Quota / Licensing
    on Feb 26, 2026
  2. EricRahm commented on Feb 26, 2026

    @EricRahm
    ContributorAuthor

    I suspect #17170 might be relevant here and perhaps related to #18508

  3. jerop commented on Feb 26, 2026

    @jerop
    Contributor
  4. added a commit that references this issue on Feb 28, 2026
    df4cd47
  5. EricRahm commented on Feb 28, 2026

    @EricRahm
    ContributorAuthor

    @jerop just fyi drafted up a PR along with a couple integration tests for policy engine in #20639 No worries if y'all have other plans, hopefully it's helpful either way!

  6. jerop commented on Mar 2, 2026

    @jerop
    Contributor

    Thank you @EricRahm - @kschaab will review and advise

  7. added
    help wantedWe will accept PRs from all issues marked as "help wanted". Thanks for your support!
    and removed
    status/need-triageIssues that need to be triaged by the triage automation.
    on Mar 2, 2026
  8. added a commit that references this issue on Mar 2, 2026
    d2892e9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area/enterpriseIssues related to Telemetry, Policy, Quota / Licensinghelp wantedWe will accept PRs from all issues marked as "help wanted". Thanks for your support!

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions