fix(hooks): share one SSRF policy instead of a second, stale copy

The hook runner carried its own `is_blocked_ip`, a line-for-line copy of
the pre-hardening web_fetch predicate: loopback allowed unconditionally,
and no TEST-NET, 198.18/15, 240/4, 0.0.0.0/8, multicast, IPv6 site-local
or embedded-v4 wrapper coverage. Hook URLs come from settings, and
project settings from an untrusted repo are loaded today, so the gap is
reachable.

`kigi-hooks` already depends on `kigi-tools`, so the fix is to delete the
copy and call the shared predicate — no new crate, and no third
implementation to drift.

`allow_local` is on for hooks: a loopback hook receiver is a legitimate
local setup, which the old copy also allowed. It is now allowed only
when the URL names the host literally, so a public name resolving to
loopback is refused.

Range coverage now lives with the policy; the runner's tests pin what it
adds on top. The URL-scrubbing regression test moves off TEST-NET-1,
which the policy now blocks, onto a closed loopback port — faster, and
no real egress from a test.
This commit is contained in:
ZacharyZhang-NY committed 2026-07-27 13:01:50 -04:00
1 parent 74402f3078
commit bac8470c80
3 files changed
+61 -139

No files matched your search

@@ -14,7 +14,7 @@ pub mod domain;
pub mod error;
mod http;
pub(crate) mod overflow;
mod ssrf;
pub mod ssrf;
pub use client::WebFetchClient;
pub use config::WebFetchParams;