You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Security / v0.5.3] Harden webhook SSRF guard against DNS rebinding (TOCTOU between pre-resolve and requests.post) #14
_is_private_destination() in forgelm/webhook.py pre-resolves the webhook hostname via socket.getaddrinfo to block private/loopback destinations. However, requests.post() performs its own DNS resolution when making the actual connection, creating a TOCTOU window: an attacker-controlled DNS server could return a public IP on the first lookup (passing the check) and a private IP on the second lookup (when requests connects), bypassing the SSRF guard.
Existing mitigations (already in place)
allow_private_destinations: false is the default in WebhookConfig — operators must explicitly opt in to private destinations.
allow_redirects=False prevents redirect-chaining to a private destination after a valid initial response.
The attack surface is narrow: requires attacker control of the DNS server for the configured webhook domain.
Proposed fix direction
Resolve the hostname to a concrete public IP inside _is_private_destination() (or a new helper) and return that IP alongside the boolean result.
Reconstruct the webhook URL with the IP literal.
Pass the original hostname in a Host header.
For HTTPS, register requests_toolbelt.adapters.host_header_ssl.HostHeaderSSLAdapter on a per-call Session to preserve SNI and certificate validation against the original hostname.
Keep allow_redirects=False.
Dependencies / complexity
Adds requests-toolbelt as a dependency (new hard dep or optional extra — TBD).
Requires careful SNI/cert validation testing across supported requests versions.
Should land in its own isolated commit/PR so it can be reverted cleanly if behaviour differs across requests releases.
Target
v0.5.3 hardening cycle. Deferred from v0.5.2 (Phase 12) to keep the HostHeaderSSLAdapter wiring reviewable in isolation.
Activity
docs(post-merge): refresh roadmap + README + CHANGELOG to match merge…
docs(post-merge): refresh roadmap + README + CHANGELOG to match merge…
fix(wave-5-pr-34-round3): absorb 26 CodeRabbit OOD/Minor + 24 multi-a…
feat(wizard): review-cycle 3 — bug fixes + UX polish
fix: PR #52 review-round-2 — switch request_headers to CaseInsensitiv…
Merge pull request #52 from cemililik/fix/webhook-dns-rebinding-issue-14
fix: PR #54 review pass 3 — 5 valid findings (markdownlint + test list)
fix: nightly CI + 4 review findings (3 valid + 1 skipped)
fix(http): strip port from Host header before TLS assert_hostname (M6…
Full-project-review remediation: Waves 1–4 (H2→N1, 78 commits) (#63)