Problem
WebClient._validate_host_ip() in src/gaia/web/client.py resolves the hostname via socket.getaddrinfo(), validates the IP is public, then hands the URL to requests, which resolves the hostname again on connect. A carefully timed DNS rebind (low-TTL record) can pass validation with a public IP and connect to an RFC1918 address (e.g. 127.0.0.1, 169.254.169.254).
Risk Assessment
Low for GAIA's threat model (local-first desktop agent). Exploitation requires:
- Attacker controls a DNS record the user visits
- Attacker times the TTL rotation between validation and connect
- The target internal service must be reachable from the user's machine
Fix Options
- Pin resolved IP: Resolve once, inject the IP into the connection via a custom
urllib3 HTTPAdapter or Host header rewrite
- Re-validate post-connect: Check the peer address from the established socket against the blocklist
- Document the limitation: Add a comment noting the window (already done in PR review comments)
Option 1 is the most robust but requires lower-level socket control than requests exposes cleanly.
Files
src/gaia/web/client.py — _validate_host_ip() (~line 132) and _request() (~line 196)
Identified during code review of #495, acknowledged as acceptable tradeoff by 3 independent reviewers.
Problem
WebClient._validate_host_ip()insrc/gaia/web/client.pyresolves the hostname viasocket.getaddrinfo(), validates the IP is public, then hands the URL torequests, which resolves the hostname again on connect. A carefully timed DNS rebind (low-TTL record) can pass validation with a public IP and connect to an RFC1918 address (e.g.127.0.0.1,169.254.169.254).Risk Assessment
Low for GAIA's threat model (local-first desktop agent). Exploitation requires:
Fix Options
urllib3HTTPAdapterorHostheader rewriteOption 1 is the most robust but requires lower-level socket control than
requestsexposes cleanly.Files
src/gaia/web/client.py—_validate_host_ip()(~line 132) and_request()(~line 196)Identified during code review of #495, acknowledged as acceptable tradeoff by 3 independent reviewers.