Skip to content

fix(security): WebClient DNS rebinding TOCTOU in SSRF check #956

@kovtcharov-amd

Description

@kovtcharov-amd

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:

  1. Attacker controls a DNS record the user visits
  2. Attacker times the TTL rotation between validation and connect
  3. The target internal service must be reachable from the user's machine

Fix Options

  1. Pin resolved IP: Resolve once, inject the IP into the connection via a custom urllib3 HTTPAdapter or Host header rewrite
  2. Re-validate post-connect: Check the peer address from the established socket against the blocklist
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions