Skip to content

fix(zetesis): close indexer-fetch SSRF, injection, XML-DoS, and key-leak defects - #556

Merged
forkwright merged 1 commit into
mainfrom
fix/zetesis-fetch-security
Jul 3, 2026
Merged

fix(zetesis): close indexer-fetch SSRF, injection, XML-DoS, and key-leak defects#556
forkwright merged 1 commit into
mainfrom
fix/zetesis-fetch-security

Conversation

@forkwright

Copy link
Copy Markdown
Owner

Closes a cluster of SECURITY defects on the indexer-fetch path (deep-audit).

Gate kanon gate --full green (1833 tests); new regression test per fix.

Closes #518
Closes #519
Closes #520
Closes #521
Closes #532
Closes #550

…eak defects

Adversarial audit found a cluster of security defects on the indexer-fetch
path. Each is closed at its enforcement point:

- SSRF DNS-rebinding TOCTOU: validate_fetch_url checked resolved IPs then
  discarded them; the shared client re-resolved at connect time. Add an
  SsrfGuardResolver (reqwest::dns::Resolve) that re-checks every resolved
  address at connect time and rejects disallowed ones; wire it into the
  shared client. Pre-check kept as defense-in-depth.
- IPv4-compatible IPv6 (::/96) gap: ip_is_disallowed omitted the deprecated
  ::a.b.c.d embed, so [::127.0.0.1] passed. Port net_validate's exact
  handling (mapped -> v6 specials -> ::/96 embed).
- Cardigann $raw injection: $raw inputs rendered variable expansions
  unescaped and spliced into the query via set_query, so a term like
  'a&b=c' injected extra params. Encode $raw expansions via render_url,
  matching the search-path encoding; literal $raw structure untouched.
- API keys leaked via tracing spans: download()/get_inner() were
  #[instrument] without skipping the url arg, capturing apikey= as a span
  field. Skip url on every secret-bearing instrumented fn in the client tree.
- cf_bypass skipped the body-size cap: ByparrProxy::get read via
  response.json() with no cap, making max_response_body_bytes a no-op for
  cf_bypass indexers. Enforce the cap (Content-Length precheck + streamed
  counter) on the byparr envelope before buffering.
- Untrusted caps XML stack overflow: parse_caps_xml deserialized into the
  self-referential CapsCategory, overflowing the stack during serde's
  recursive descent before the iterative converter ran. Bound XML nesting
  depth on the raw event stream before deserialization.

Gate-Passed: kanon 0.1.5 +stages:fmt,check,clippy,nextest,lint sha:29a0bba2e9f4fb3081110d37bc6dc2445c23514d
@forkwright
forkwright merged commit f3bafb2 into main Jul 3, 2026
12 checks passed
@forkwright
forkwright deleted the fix/zetesis-fetch-security branch July 3, 2026 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment