Skip to content

Fail closed for high-risk tools without explicit confirmation policy#4626

Open
davidahmann wants to merge 1 commit intogoogle:mainfrom
davidahmann:codex/issue-4625-high-risk-tool-confirmation
Open

Fail closed for high-risk tools without explicit confirmation policy#4626
davidahmann wants to merge 1 commit intogoogle:mainfrom
davidahmann:codex/issue-4625-high-risk-tool-confirmation

Conversation

@davidahmann
Copy link

Problem

High-risk tools can execute when confirmation policy is missing or permissive, which weakens safety boundaries and increases blast radius for tool-invocation mistakes.

Why now

Issue #4625 requests fail-closed behavior for high-risk tooling so unsafe operations are blocked unless explicit confirmation policy exists.

What changed

  • Added is_high_risk support for FunctionTool and MCP tools.
  • Enforced fail-closed behavior: high-risk tool execution now returns an explicit error when confirmation policy is not enabled.
  • Propagated high-risk classification through MCP toolset construction.
  • Added focused unit tests covering new fail-closed behavior for function and MCP tools.

Validation

  • uv run pyink --check --diff src/google/adk/tools/function_tool.py src/google/adk/tools/mcp_tool/mcp_tool.py src/google/adk/tools/mcp_tool/mcp_toolset.py tests/unittests/tools/test_function_tool.py tests/unittests/tools/mcp_tool/test_mcp_tool.py (pass)
  • uv run pytest tests/unittests/tools/test_function_tool.py tests/unittests/tools/mcp_tool/test_mcp_tool.py -k 'high_risk_without_confirmation_policy or require_confirmation' (pass)

Refs #4625

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @davidahmann, 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 enhances the safety boundaries of tool execution by introducing a "fail-closed" policy for high-risk tools. Previously, such tools could execute without explicit confirmation if a policy was missing or permissive. The changes ensure that any tool designated as high-risk will now explicitly error out if a clear confirmation policy is not defined, thereby preventing unintended or unsafe operations and reducing potential blast radius.

Highlights

  • High-Risk Tool Identification: Introduced an is_high_risk flag for both FunctionTool and MCPTool to explicitly mark tools that perform high-impact operations.
  • Fail-Closed Mechanism: Implemented a 'fail-closed' behavior for high-risk tools, ensuring they return an explicit error if executed without a clear confirmation policy (i.e., require_confirmation is not set to True or a callable that returns True).
  • High-Risk Flag Propagation: Ensured that the is_high_risk classification is correctly propagated from MCPToolset to the individual MCPTool instances it constructs.
  • Unit Test Coverage: Added dedicated unit tests to validate the new fail-closed behavior for both FunctionTool and MCPTool.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/google/adk/tools/function_tool.py
    • Added is_high_risk parameter to the FunctionTool constructor.
    • Stored the is_high_risk value as an instance attribute.
    • Modified run_async to check if the tool is high-risk and if require_confirmation is not set, returning an error if both conditions are met.
  • src/google/adk/tools/mcp_tool/mcp_tool.py
    • Added is_high_risk parameter to the MCPTool constructor.
    • Stored the is_high_risk value as an instance attribute.
    • Modified run_async to implement the fail-closed logic for high-risk tools without confirmation.
  • src/google/adk/tools/mcp_tool/mcp_toolset.py
    • Added is_high_risk parameter to the MCPToolset constructor.
    • Stored the is_high_risk value as an instance attribute.
    • Passed the is_high_risk value to the MCPTool instances created within the get_tools method.
  • tests/unittests/tools/mcp_tool/test_mcp_tool.py
    • Added a new asynchronous test case test_run_async_high_risk_without_confirmation_policy_fails_closed to verify that high-risk MCPTool instances correctly fail closed when no confirmation policy is provided.
  • tests/unittests/tools/test_function_tool.py
    • Added a new asynchronous test case test_run_async_high_risk_without_confirmation_policy_fails_closed to verify that high-risk FunctionTool instances correctly fail closed when no confirmation policy is provided.
Activity
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.

@davidahmann
Copy link
Author

Implemented high-risk tool fail-closed behavior for FunctionTool and MCP tools when explicit confirmation policy is not enabled, with focused unit coverage for both paths.

This contribution was informed by patterns from Wrkr. Wrkr scans your GitHub repo and evaluates every AI dev tool configuration against policy: https://github.com/Clyra-AI/wrkr

@adk-bot adk-bot added the tools [Component] This issue is related to tools label Feb 25, 2026
Copy link
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 successfully implements the "fail closed" behavior for high-risk tools by adding an is_high_risk flag. The changes ensure that high-risk tools will return an error if a confirmation policy is not explicitly enabled, which enhances safety. The implementation is consistent across FunctionTool and MCPTool, and the new behavior is well-tested. My main feedback is to extract the duplicated error message into a shared constant to improve maintainability.

Comment on lines +202 to +206
'error': (
'This high-risk tool requires an explicit confirmation policy.'
' Set require_confirmation=True or provide a callable policy'
' that returns True.'
)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This error message is duplicated in src/google/adk/tools/mcp_tool/mcp_tool.py and also hardcoded in the corresponding test files (tests/unittests/tools/test_function_tool.py and tests/unittests/tools/mcp_tool/test_mcp_tool.py). To improve maintainability and avoid inconsistencies, it's best to define this string as a constant in a shared module (e.g., a new src/google/adk/tools/constants.py) and import it in all places where it's used. This ensures that any future changes to the message only need to be made in one place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tools [Component] This issue is related to tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants