SSRF: DNS pinning is never applied (WordPress ignores $args['curl']) #3
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
eric/apprise-wordpress-notifications#3
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found in security audit run 3 (2026-10-16,
06d630d). Severity: low.Problem
Apprise_Client::make_request()tries to pin the validated IP by setting$args['curl'][ CURLOPT_RESOLVE ](includes/class-apprise-client.php:237), then callswp_remote_post()with the hostname URL (:239,:261).WordPress core never reads a
curlkey.WP_Http::request()builds the Requests options without it (checked against 7.1.3), so the pin is silently dropped and cURL looks the hostname up again when it connects. The IP that was validated and the IP actually contacted can therefore differ. Anyone controlling DNS for the configured host can rebind it, or publish a public A record plus an internal or loopback AAAA record, and get past the private/reserved-IP check.resolve_hostname()checks only the first A record, while cURL prefers IPv6.The same root cause makes
sanitize_curl_options()dead code: filter-injected cURL options were never applied either.Reproduced locally: the real client's arguments, sent through unmodified
WP_Http, fail with "Could not resolve host". The same pin applied throughhttp_api_curlconnects.Fix
CURLOPT_RESOLVEto the real handle from thehttp_api_curlaction. Scope it to this request's URL, register it atPHP_INT_MAX, andremove_actionafterwp_remote_postreturns.$args['curl']handling, or movesanitize_curl_options()to act on the handle in the same callback.:183-186, which promises pinning that doesn't happen.make_request()registers anhttp_api_curlcallback that sets the validatedhost:port:ip.