fix(web_fetch): block non-public targets by default and gate every hop
kigi allowed loopback unconditionally and missed several non-public ranges, and the SSRF check ran only on the initial URL. Policy (ssrf.rs): - loopback is blocked unless `[toolset.web_fetch] allow_local` (or KIGI_WEB_FETCH_ALLOW_LOCAL) is on, AND the URL names it explicitly, so a public name resolving to loopback stays blocked (DNS rebinding) - add 0.0.0.0/8, 100.64/10, 192.0.0.0/24, TEST-NET-1/2/3, 198.18/15, 240/4, IPv6 site-local and documentation prefixes - inherit the IPv4 verdict through mapped, compatible, NAT64 and 6to4 wrappers; network-specific NAT64 prefixes remain uncovered (see doc) Plumbing (client.rs), where the exploitable half lived: - re-check every redirect hop, not just the first - compare hosts exactly; a `www` sibling has its own A records, so it is a cross-host redirect rather than an auto-followed hop - run the check before the fetch service, so a blocked URL is never posted to an endpoint that egresses elsewhere - exempt explicit local hosts from the https upgrade and from the single-label filter, and re-upgrade each followed hop Wiring: allow_local reaches WebFetchParams from both construction paths; documented in the config guide and the README env table.
This commit is contained in:
@@ -225,8 +225,16 @@ timeout_secs = 1800 # seconds to wait when enabled (default:
|
||||
[toolset.web_fetch]
|
||||
proxy_endpoint = "https://proxy.example.com" # egress proxy URL
|
||||
allowed_domains = ["docs.rs", "x.ai"] # override the built-in allowlist
|
||||
allow_local = false # true = reach localhost / 127.0.0.0/8 / ::1
|
||||
```
|
||||
|
||||
`allow_local` opens **loopback only**, and only when the URL names it
|
||||
explicitly (`http://127.0.0.1:8080/`, `http://localhost:3000/`). A public
|
||||
domain whose DNS record points at loopback stays blocked — that is DNS
|
||||
rebinding, not local development. Private, link-local, CGNAT and cloud
|
||||
metadata ranges are never reachable, with or without this flag. Precedence:
|
||||
user config → `KIGI_WEB_FETCH_ALLOW_LOCAL` → off.
|
||||
|
||||
`[toolset.ask_user_question]` is honored across **requirements.toml**, **managed
|
||||
config**, and **user `config.toml`**. Precedence: requirements → env
|
||||
(`KIGI_ASK_USER_QUESTION_TIMEOUT_ENABLED` /
|
||||
|
||||
Reference in New Issue
Block a user