feat(webhook): harden signed callback transport and bind DNS validation to dial authority - #85675
feat(webhook): harden signed callback transport and bind DNS validation to dial authority#85675andrexibiza wants to merge 1 commit into
Conversation
|
This was generated by AI during triage. Summary: Problems:
Solution: Evidenceno deterministic fact backs this claim — model belief, not executed or read evidence Checked against |
feat(webhook): add SSRF-guarded signed completion callbacks (Webhook Feature Package)
|
f146af2 to
bb27b3a
Compare
andrexibiza
left a comment
There was a problem hiding this comment.
Published a replacement head for this review train: bb27b3a39e93f66540c416bc5e73508441f098ad, rebased directly onto current main as a one-commit/two-file transport object.
The DNS-rebinding finding was correct and is fixed at the authority boundary rather than by wording: resolution now produces the exact address the socket dials. HTTPS still verifies/SNIs against the configured hostname and preserves the original Host authority, so there is no second DNS lookup between SSRF validation and connect. Any unsafe answer fails the entire resolution set closed.
The same head also adds deliver_callback_async() via asyncio.to_thread so DNS/connect/TLS/response I/O and retry backoff stay off the gateway event loop, treats 3xx as terminal without following redirects, and rejects malformed envelopes before DNS/retry work.
I also narrowed the PR claim: this is the callback transport authority only. Runtime true-completion wiring remains with #85645/#85640 rather than introducing a second completion owner here. Fresh exact-head CI/Docker/Nix is running; no historical green is inherited.
|
@teknium1 maintainer review requested on exact head Revalidated now: open/non-draft/mergeable; exact-head CI This lane should remain the callback transport authority only: DNS validation is bound to the dial target, redirects fail closed, response/retry work is bounded, and gateway use is async-wrapped. #85645 owns true completion timing; #85640 owns final integration. Please review/merge without folding those distinct authorities back together. |
Part of #84834 — Webhook Feature Package callback transport. Related #4386 / #73828.
Current ownership
This PR owns the outbound callback transport primitive, not the runtime completion-hook integration. The branch has been semantically compressed onto current
mainso it no longer carries campaign receipts or contributor-map churn.Exact topology:
f43eabee5f36e11448086ee8ee17c499958e81bfbb27b3a39e93f66540c416bc5e73508441f098adRuntime completion ownership remains separate: #85645 owns the true-end-of-run completion seam; #85640 is the terminal integration lane that composes callback transport with the final webhook package. This PR does not claim to close #4386/#73828 by itself.
Transport contract
Hostauthority;deliver_callback_async()viaasyncio.to_thread, so gateway callers do not block the event loop during DNS/connect/TLS/response I/O or backoff.Review fixes
The previous "per-address resolution check" was not sufficient: validation and
urllibconnect performed different DNS lookups. That TOCTOU/rebinding class is now closed by binding validation output to the actual dial target. The blocking-I/O and malformed-envelope findings are also covered by focused regressions.Exact-head verification
At
bb27b3a39e93f66540c416bc5e73508441f098ad:32391837152— success32391835648— success32391835383— successThese receipts are attached to the one-commit replacement head itself; no historical checks are inherited.