A webhook security review needs evidence of which destinations the system accepts and which addresses it can reach. That evidence should cover URL validation, DNS resolution, configuration paths, and outbound connections. Each boundary matters when callbacks could expose internal networks or metadata services.
Strict endpoint restrictions give security reviewers concrete checks to assess. In MailWebhook, the endpoint UI validates URLs and their resolved addresses when endpoints are created or edited. Those checks screen the UI configuration at that moment. API creation and updates use HTTP URL validation without invoking the DNS/address policy, and persistence adds no equivalent check. The delivery engine later sends to the stored hostname without repeating the address-policy check or pinning a validated address. Approval needs to account for both the API enforcement gap and the risk of later DNS changes.
This post follows Webhook Signature Verification with HMAC, which covers how receivers verify signed deliveries. Destination restriction is the companion control, with separate requirements for accepting an endpoint and enforcing the destination of each connection. Here, I go deeper on Question 2 from Webhook Security for Email Automation, examining the scope and limits of callback destination validation.
For product context, see MailWebhook’s Email Webhook API for the inbound email-to-webhook integration this review examines.
Public-network-only callback policy: defining the boundary reviewers should test
Key term: Public-network-only callback policy sets public IP addresses as the allowed destination class. Enforcing that policy requires checks at each relevant boundary, including the actual outbound connection.
I start a review by documenting the intended policy: callback targets must use public addresses. RFC 1918 defines private IPv4 ranges that reviewers can include in rejection tests. (RFC 1918: Address Allocation for Private Internets)
IANA identifies private-use addresses and their intended scope. Use those classifications to define expected outcomes for test inputs, then record the result for each configuration path. (IANA: Private-use IP addresses)
This matters even more for systems that trigger callbacks automatically. If the answer includes internal hosts, lab systems, management planes, or private services, the review surface grows fast. A public-only policy gives the security team a specific requirement to test at configuration time and at connection time.
A useful review record pairs each test destination with its address category, the configuration path used, the expected decision, and the observed result. Include both endpoint creation and updates through the UI and API. Record missing checks as gaps.
URL hygiene enforcement: what a clean destination looks like
Key term: URL hygiene enforcement means parsing and validating callback URLs at configuration time to reject destinations that fail the configured URL rules.
URL hygiene review should include examples with embedded credentials, unusual encodings, unexpected ports, and malformed structure. Record how the validator and HTTP client interpret each input so reviewers can identify inconsistent handling. (OWASP Server-Side Request Forgery Prevention Cheat Sheet)
As a general design recommendation, use a standard URL parser and define explicit rules for accepted components and encodings. If canonicalization is part of the design, test that validation and the HTTP client interpret the resulting URL consistently. Reviewers should also ask how the system handles fragments, embedded credentials, and ambiguous encodings. These are review criteria; each needs evidence of implementation. (OWASP Input Validation Cheat Sheet)
This is especially important in products that trigger outbound actions automatically, including systems that support an email routing rules API, conditional email routing, or an email filter webhook. In those flows, a destination often enters the system through configuration and then runs later without a human watching each event. If the URL is sloppy at intake, the risk stays hidden until the automation fires.
MailWebhook’s endpoint UI calls a shared validator that parses the URL with urllib.parse.urlparse. It checks for an allowed http or https scheme, a hostname, nonempty username or password fields, port validity, and blocked address categories after resolution. The shared validator does not explicitly reject fragments, implement a canonicalization step, or apply a dedicated ambiguous-encoding check. Those broader design recommendations should not be read as implemented MailWebhook controls.
API creation and updates use Pydantic’s HttpUrl for URL validation. Both paths omit the shared DNS/address validator. The persistence layer stores the URL without adding that policy check. The verified address restriction therefore applies to the UI path; it is not enforced across all endpoint configuration paths.
Use the endpoint configuration documentation for endpoint settings and the HTTP request contract. Its public-address restrictions are stated without the path-specific qualification above. The API and delivery-time enforcement gaps remain unresolved in the implementation reviewed here, so this documentation does not establish universal destination protection.
The payoff is a concrete review record: which URL checks run, where they run, and which inputs they reject. That gives teams a repeatable way to assess endpoint configuration.
Resolved-address safety checks: why hostname review is too shallow
Key term: Resolved-address safety checks mean inspecting the IP addresses returned for a hostname and rejecting validation if any address matches a blocked range. The result applies to the addresses observed during that lookup.
For resolved-address review, capture the DNS answers used during validation and the decision for each returned address. Include loopback, private, link-local, multicast, and reserved ranges in the test cases. (OWASP Server-Side Request Forgery Prevention Cheat Sheet)
MailWebhook’s shared URL validator checks literal IP addresses directly and resolves hostnames to inspect the returned addresses. It rejects addresses classified as private, loopback, link-local, reserved, or multicast. The endpoint UI invokes this validator during creation and editing. IPv6 needs attention too: RFC 4193 defines unique local IPv6 addresses, so a review limited to private IPv4 ranges would miss part of the policy. (RFC 4193: Unique Local IPv6 Unicast Addresses)
That validation is a snapshot. MailWebhook’s delivery engine passes the stored URL to its HTTP client without invoking the address validator or pinning the connection to an address that passed validation. A hostname can resolve differently later, including during a DNS rebinding attack. OWASP explicitly identifies trusting initial DNS resolution as a pitfall. Configuration-time checks therefore cannot establish that every delivery reaches an allowed address. (OWASP SSRF Prevention in Node.js)
For approval, record the verified boundary as endpoint UI configuration validation. A delivery-time guarantee would require evidence that the address actually used for the connection is constrained by policy, through connection-level validation and enforcement or equivalent network controls. That guarantee is outside the protection established by the implementation reviewed here.

SSRF-risk reduction by design: separating configuration checks from delivery safeguards
Key term: SSRF-risk reduction by design means building destination restrictions into the delivery system to limit how attackers can use server-side requests to reach unintended resources.
The review should distinguish evidence about accepted configuration from evidence about actual outbound connections. SSRF lets an attacker influence a server-side request to reach unintended resources. For each claimed safeguard, identify the enforcement point and a test that demonstrates its scope. (OWASP Server-Side Request Forgery Prevention Cheat Sheet)
The following inventory reflects source inspection of the reviewed implementation. Runtime behavior and deployment-level network controls need separate verification.
| Enforcement point | Verified checks | Limit of protection |
|---|---|---|
| Endpoint UI creation and editing | Shared validator checks scheme, hostname, credentials, port validity, and resolved address categories. | Applies at configuration time; no explicit fragment rejection or canonicalization step. |
| API endpoint creation and updates | Pydantic HttpUrl validates the URL. |
Neither path invokes the shared DNS/address policy. |
| Endpoint persistence | Stores the supplied URL. | Adds no equivalent DNS/address-policy check. |
| HTTP delivery engine | Sends to the stored URL through the HTTP client. | Does not invoke the address validator or pin a validated address for the connection. |
For delivery-time evidence, use a controlled test environment to change a test hostname’s DNS answer after configuration and observe the destination used by the connection. Record the resolved address, connection target, and any application or network rejection. This is a proposed review test; the source inspection described here does not establish its runtime outcome.
The practical value gets sharper when sensitive internal services enter the picture. AWS guidance calls out instance metadata as a common SSRF target and recommends IMDSv2 as defense in depth, which shows the risk is important enough to design around at the platform layer. (AWS Prescriptive Guidance: Application Security Reference Architecture)
API address-policy enforcement and delivery-time destination enforcement remain gaps in the reviewed application. A platform-wide restriction claim would require evidence that these gaps are closed.

The current source review establishes a limited control boundary. MailWebhook’s endpoint UI checks URL structure and resolved addresses during configuration. These checks reject certain unsafe inputs through the UI at that point. API creation and updates lack the same address-policy enforcement. A successful UI check also does not establish that later connections use the same addresses or stay within policy after DNS changes.
Strict callback boundaries are useful when teams can show exactly where they are enforced. Document which configuration paths enforce the policy, assess the API and delivery-time gaps, and base approval on the controls verified for the deployment.
