Skip to content

fix: add SSRF protection to RestApiTool._request()#5760

Open
Neelagiri65 wants to merge 1 commit into
google:mainfrom
Neelagiri65:fix/ssrf-protection-rest-api-tool
Open

fix: add SSRF protection to RestApiTool._request()#5760
Neelagiri65 wants to merge 1 commit into
google:mainfrom
Neelagiri65:fix/ssrf-protection-rest-api-tool

Conversation

@Neelagiri65
Copy link
Copy Markdown

What

RestApiTool._request() passes URLs to httpx.AsyncClient.request() with no validation. After #4368 fixed SSRF in load_web_page (hostname blocking, DNS pre-resolution, IP range filtering, scheme restriction), RestApiTool was not updated with the same protections.

An OpenAPI spec with servers[].url pointing at 127.0.0.1 or 169.254.169.254 goes through without any check.

Changes

  • New shared module _ssrf_protection.py with the validation logic (scheme check, hostname blocking, DNS resolution, IP range filtering)
  • _request() calls validate_url() before making the HTTP request
  • Timeout changed from None to 30 seconds
  • 24 new tests covering blocked hosts, schemes, and the _request integration

What gets blocked

  • localhost and *.localhost
  • Loopback (127.0.0.0/8, ::1)
  • Link-local (169.254.0.0/16) — covers cloud metadata endpoints
  • Private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
  • Non-http(s) schemes (file://, ftp://, etc.)

Why a shared module

load_web_page.py has its own copies of these functions. The shared module avoids duplicating the logic a third time. load_web_page can be migrated to use it in a follow-up if wanted.

Related: #4368

RestApiTool._request() passes URLs straight to httpx with no validation.
load_web_page got SSRF protections after google#4368 (hostname blocking, DNS
pre-resolution, IP range filtering, scheme restriction) but RestApiTool
was not updated.

This extracts the SSRF validation logic into a shared _ssrf_protection
module and applies it in _request() before making HTTP calls. Also sets
a finite timeout (30s) instead of None.

Blocked: localhost, *.localhost, loopback, link-local (169.254.x.x),
private ranges (10.x, 172.16-31.x, 192.168.x), non-http(s) schemes.

Related: google#4368
@google-cla
Copy link
Copy Markdown

google-cla Bot commented May 20, 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.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant