Skip to content

🚨 Severity: HIGH Vulnerability: SSRF in load_web_page tool#4368

Closed
Nandan-D14 wants to merge 2 commits intogoogle:mainfrom
Nandan-D14:main
Closed

🚨 Severity: HIGH Vulnerability: SSRF in load_web_page tool#4368
Nandan-D14 wants to merge 2 commits intogoogle:mainfrom
Nandan-D14:main

Conversation

@Nandan-D14
Copy link

🚨 Severity: HIGH
💡 Vulnerability: SSRF in load_web_page tool. The tool allowed fetching arbitrary URLs including internal IPs (localhost, 192.168.x.x) and lacked timeout protection.
🎯 Impact: Attackers could access internal services, metadata services, or cause DoS.
🔧 Fix: Added _is_safe_url validation to check scheme, block private IPs (direct and resolved), and added a 10s timeout.
✅ Verification: Added tests/unittests/tools/test_load_web_page.py verifying that private IPs are blocked and public URLs are allowed.

google-labs-jules bot and others added 2 commits February 4, 2026 11:15
🚨 Severity: HIGH
💡 Vulnerability: SSRF in load_web_page tool. The tool allowed fetching arbitrary URLs including internal IPs (localhost, 192.168.x.x) and lacked timeout protection.
🎯 Impact: Attackers could access internal services, metadata services, or cause DoS.
🔧 Fix: Added `_is_safe_url` validation to check scheme, block private IPs (direct and resolved), and added a 10s timeout.
✅ Verification: Added `tests/unittests/tools/test_load_web_page.py` verifying that private IPs are blocked and public URLs are allowed.

Co-authored-by: Nandan-D14 <154668653+Nandan-D14@users.noreply.github.com>
…-675239147882500237

🛡️ Sentinel: [HIGH] Fix SSRF in load_web_page
@google-cla
Copy link

google-cla bot commented Feb 4, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @Nandan-D14, 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 delivers a critical security enhancement by patching a high-severity Server-Side Request Forgery (SSRF) vulnerability within the load_web_page tool. The previous implementation allowed the tool to fetch content from arbitrary URLs, including internal network resources, posing a significant risk of data exposure or denial of service. The fix introduces robust URL validation and timeout mechanisms, significantly hardening the tool against malicious exploitation.

Highlights

  • SSRF Vulnerability Fix: Addressed a high-severity Server-Side Request Forgery (SSRF) vulnerability in the load_web_page tool, which previously allowed fetching arbitrary URLs including internal IPs.
  • Robust URL Validation: Implemented a new _is_safe_url function to strictly validate URLs, ensuring only http or https schemes are used and blocking access to private, loopback, link-local, and unspecified IP addresses, including those resolved from hostnames.
  • Timeout Protection: Added a 10-second timeout to web requests made by load_web_page to prevent potential Denial of Service (DoS) attacks.
  • New Unit Tests: Introduced comprehensive unit tests for load_web_page to verify that private IPs are correctly blocked and public URLs are allowed, ensuring the security fix is effective.
  • Security Documentation: Added a new sentinel document (.jules/sentinel.md) detailing the SSRF vulnerability, lessons learned, and prevention strategies.

🧠 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
  • .jules/sentinel.md
    • Added a new security documentation entry for the SSRF vulnerability in the load_web_page tool, outlining the vulnerability, lessons learned, and prevention methods.
  • contributing/dev/utils/build_llms_txt.py
    • Applied minor code formatting and linting adjustments.
  • contributing/samples/cache_analysis/run_cache_experiments.py
    • Adjusted string formatting for print statements to improve readability.
  • contributing/samples/gepa/experiment.py
    • Applied minor code formatting and linting adjustments.
  • contributing/samples/gepa/run_experiment.py
    • Applied minor code formatting and linting adjustments.
  • contributing/samples/gepa/tau_bench_agent.py
    • Applied minor code formatting and linting adjustments.
  • contributing/samples/human_in_loop/main.py
    • Applied minor code formatting and linting adjustments.
  • contributing/samples/langchain_structured_tool_agent/agent.py
    • Applied minor code formatting and linting adjustments.
  • contributing/samples/session_state_agent/agent.py
    • Applied minor code formatting and linting adjustments.
  • contributing/samples/static_instruction/agent.py
    • Applied minor code formatting and linting adjustments.
  • contributing/samples/token_usage/main.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/agents/common_configs.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/artifacts/gcs_artifact_service.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/init.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/adk_agent_builder_assistant.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/agent.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/sub_agents/init.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/sub_agents/google_search_agent.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/sub_agents/url_context_agent.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/tools/init.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/tools/delete_files.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/tools/explore_project.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/tools/query_schema.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/tools/read_config_files.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/tools/read_files.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/tools/search_adk_knowledge.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/tools/search_adk_source.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/tools/write_files.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/utils/init.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/utils/adk_source_utils.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/built_in_agents/utils/resolve_root_directory.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/cli/utils/local_storage.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/examples/vertex_ai_example_store.py
    • Wrapped long expressions in parentheses for better code formatting.
  • src/google/adk/flows/llm_flows/_base_llm_processor.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/flows/llm_flows/audio_cache_manager.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/flows/llm_flows/interactions_processor.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/sessions/_session_util.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/sessions/migration/migration_runner.py
    • Applied minor code formatting and linting adjustments.
  • src/google/adk/tools/application_integration_tool/clients/connections_client.py
    • Wrapped long f-strings in parentheses for better code formatting.
  • src/google/adk/tools/bigtable/metadata_tool.py
    • Adjusted tuple unpacking for better readability.
  • src/google/adk/tools/load_web_page.py
    • Imported ipaddress, socket, and urllib.parse for URL and IP validation.
    • Introduced _is_safe_url function to perform strict URL validation, checking for allowed schemes (http/https), blocking private/loopback/link-local/unspecified IP addresses, and resolving hostnames to check for private IPs.
    • Modified load_web_page to use _is_safe_url to prevent fetching restricted URLs.
    • Added a timeout=10 parameter to requests.get to prevent indefinite waits and potential DoS.
    • Implemented try-except requests.RequestException for robust error handling during web requests.
  • src/google/adk/tools/mcp_tool/mcp_tool.py
    • Adjusted string concatenation for authorization headers.
  • tests/unittests/agents/test_llm_agent_error_messages.py
    • Applied minor code formatting and linting adjustments.
  • tests/unittests/agents/test_mcp_instruction_provider.py
    • Applied minor code formatting and linting adjustments.
  • tests/unittests/cli/utils/test_cli_create.py
    • Applied minor code formatting and linting adjustments.
  • tests/unittests/cli/utils/test_cli_deploy_to_cloud_run.py
    • Applied minor code formatting and linting adjustments.
  • tests/unittests/cli/utils/test_cli_tools_click.py
    • Applied minor code formatting and linting adjustments.
  • tests/unittests/evaluation/test_evaluation_generator.py
    • Wrapped a long generator expression in parentheses for better code formatting.
  • tests/unittests/evaluation/test_trajectory_evaluator.py
    • Applied minor code formatting and linting adjustments.
  • tests/unittests/flows/llm_flows/test_functions_error_messages.py
    • Applied minor code formatting and linting adjustments.
  • tests/unittests/tools/apihub_tool/clients/test_apihub_client.py
    • Wrapped a long string in parentheses for better code formatting.
  • tests/unittests/tools/openapi_tool/openapi_spec_parser/test_openapi_spec_parser.py
    • Wrapped a long string in parentheses for better code formatting.
  • tests/unittests/tools/test_function_tool.py
    • Wrapped long error message strings in parentheses for better code formatting.
  • tests/unittests/tools/test_load_web_page.py
    • Added a new test file to specifically verify the security enhancements in load_web_page.
    • Included tests to confirm that requests to private IPs (e.g., localhost, 192.168.1.1) are blocked.
    • Added a test to ensure public URLs are correctly fetched, including mocking DNS resolution.
  • tests/unittests/tools/test_set_model_response_tool.py
    • Applied minor code formatting and linting adjustments.
Activity
  • The pull request was created to address a high-severity SSRF vulnerability.
  • New security measures, including URL validation and timeout, have been implemented in the load_web_page tool.
  • Dedicated unit tests have been added to verify the effectiveness of the security fix.
  • Documentation regarding the vulnerability and its prevention has been updated.
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.

@adk-bot adk-bot added the tools [Component] This issue is related to tools label Feb 4, 2026
@adk-bot
Copy link
Collaborator

adk-bot commented Feb 4, 2026

Response from ADK Triaging Agent

Hello @Nandan-D14, thank you for creating this PR!

Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). You can visit https://cla.developers.google.com/ to see your current agreements or to sign a new one.

This information will help reviewers to review your PR more efficiently. Thanks!

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 effectively addresses a high-severity Server-Side Request Forgery (SSRF) vulnerability in the load_web_page tool. The fix is comprehensive, adding checks for URL schemes, direct private IP addresses, and DNS-resolved private IPs, along with a request timeout to mitigate DoS risks. The new unit tests are a great addition and validate the core security fix. My feedback includes a minor refactoring suggestion to improve code clarity and a recommendation for an additional test case to enhance coverage. The other changes are minor stylistic improvements.

Comment on lines +26 to +62
def _is_safe_url(url: str) -> bool:
"""Checks if the url is safe to browse."""
try:
parsed = urlparse(url)
except ValueError:
return False

if parsed.scheme not in ('http', 'https'):
return False

hostname = parsed.hostname
if not hostname:
return False

try:
# Check if the hostname is an IP address
ip = ipaddress.ip_address(hostname)
if ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_unspecified:
return False
except ValueError:
# Check if the hostname resolves to a private IP address
try:
addr_info = socket.getaddrinfo(hostname, None)
for res in addr_info:
ip_str = res[4][0]
ip = ipaddress.ip_address(ip_str)
if (
ip.is_private
or ip.is_loopback
or ip.is_link_local
or ip.is_unspecified
):
return False
except socket.gaierror:
return False

return 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

To improve readability and reduce code duplication, the IP address validation logic is repeated. You can extract this check into a nested helper function.

def _is_safe_url(url: str) -> bool:
  """Checks if the url is safe to browse."""

  def _is_restricted_ip(ip: ipaddress.ip_address) -> bool:
    """Checks if an IP address is in a restricted range."""
    return ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_unspecified

  try:
    parsed = urlparse(url)
  except ValueError:
    return False

  if parsed.scheme not in ('http', 'https'):
    return False

  hostname = parsed.hostname
  if not hostname:
    return False

  try:
    # Check if the hostname is an IP address
    ip = ipaddress.ip_address(hostname)
    if _is_restricted_ip(ip):
      return False
  except ValueError:
    # Check if the hostname resolves to a private IP address
    try:
      addr_info = socket.getaddrinfo(hostname, None)
      for res in addr_info:
        ip_str = res[4][0]
        ip = ipaddress.ip_address(ip_str)
        if _is_restricted_ip(ip):
          return False
    except socket.gaierror:
      return False

  return True

# Verify requests.get was called
mock_get.assert_called_with(url, allow_redirects=False, timeout=10)
self.assertIn('Some Public Content', result)

Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The new tests are great for verifying the SSRF fix. To make the test suite even more robust, consider adding a test case that explicitly checks for a domain name that resolves to a private IP address. This will ensure the DNS resolution check is working as expected.

Suggested change
@patch('requests.get')
@patch('socket.getaddrinfo')
def test_load_web_page_blocks_domain_resolving_to_private_ip(self, mock_getaddrinfo, mock_get):
"""Verifies that load_web_page blocks fetches to domains resolving to private IPs."""
# Mock socket resolution to a private IP
mock_getaddrinfo.return_value = [(2, 1, 6, '', ('192.168.1.1', 80))]
url = 'http://internal.service.local'
# Call the function
result = load_web_page(url)
# Verify requests.get was NOT called
mock_get.assert_not_called()
self.assertIn('The url is restricted', result)

@Nandan-D14 Nandan-D14 closed this Feb 5, 2026
@ryanaiagent ryanaiagent self-assigned this Feb 5, 2026
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.

3 participants