Hosting · WordPress · performance · infrastructure
explainer

WordPress Outbound SSRF Mitigation: How wp_safe_remote_get and wp_http_validate_url Filter IPv4 Addresses and Ports

Short answer

Understand how WordPress mitigates outbound SSRF using wp_safe_remote_get and wp_http_validate_url, including IPv4 address range filtering, default port limits, redirect re-validation, and the risks of filter bypasses.

Research-based

Last verified:

Applies to: WordPress core HTTP API; current documented implementations of wp_safe_remote_get() and wp_http_validate_url() retrieved 2026-09-17

Comparison of WordPress safe GET wrapper and URL validator responsibilities

When a WordPress site sends an HTTP request to an arbitrary web address, such as fetching oEmbed data or pingbacks, it can risk Server-Side Request Forgery (SSRF). Without checks, outbound requests could reach internal networks, loopback addresses, or cloud metadata endpoints.

The WordPress HTTP API provides two functions to reduce these risks for outbound GET requests: wp_safe_remote_get() and wp_http_validate_url(). Together, they validate protocols, check host syntax, resolve hostnames to IPv4 addresses, block reserved IPv4 ranges, limit destination ports, and re-check redirect targets.

How wp_safe_remote_get Restricts Arbitrary GET Requests

The wp_safe_remote_get() function is designed for HTTP requests to arbitrary URLs. Under the hood, it forces URL safety validation by modifying request arguments:

function wp_safe_remote_get( $url, $args = array() ) {
    $args['reject_unsafe_urls'] = true;
    $http = _wp_http_get_object();
    return $http->get( $url, $args );
}

Setting $args['reject_unsafe_urls'] = true instructs the HTTP transport layer to validate both the initial request URL and subsequent redirect locations against wp_http_validate_url(). If validation fails at any point, the request fails and returns a WP_Error object instead of completing the connection.

The URL Validation Checks in wp_http_validate_url

The wp_http_validate_url() function accepts a URL string and returns the original URL string if valid, or false if it fails security checks. It applies the following checks in order:

1. Protocol and Host String Validation

The function first examines basic string formatting and scheme requirements:

  • Data type check: The value must be a non-empty string and not purely numeric.
  • Allowed protocols: The URL is verified with wp_kses_bad_protocol(), allowing only http and https. Protocols such as ftp:// or file:// return false.
  • Host and credentials: The URL is parsed with PHP’s parse_url(). Requests containing authentication credentials (user or pass) are rejected. If the hostname contains any of the characters :#?[], validation fails.

2. Destination IPv4 Address Filtering

If the host does not match the host configured in get_option( 'home' ), WordPress inspects its destination IP address:

  • IP detection and DNS resolution: If the host is an IPv4 address string matching four octets, it is used directly. Otherwise, it is resolved via PHP’s gethostbyname(). If DNS resolution fails, the function returns false.
  • Reserved range checks: The resolved IPv4 address is split into octets and evaluated against reserved and private ranges defined by IANA and RFC standards. By default, requests resolving to the following IPv4 ranges return false:
IPv4 Address Range / CIDR Designation or Purpose
0.0.0.0/8 This network
10.0.0.0/8 Private network (RFC 1918)
100.64.0.0/10 Carrier-Grade NAT (RFC 6598)
127.0.0.0/8 Loopback addresses
169.254.0.0/16 Link-local and cloud metadata endpoints
172.16.0.0/12 Private network (172.16.0.0 to 172.31.255.255)
192.0.0.0/24 IETF protocol assignments
192.0.2.0/24 TEST-NET-1 documentation
192.88.99.0/24 6to4 relay anycast
192.168.0.0/16 Private network (RFC 1918)
198.18.0.0/15 Benchmark testing
198.51.100.0/24 TEST-NET-2 documentation
203.0.113.0/24 TEST-NET-3 documentation
224.0.0.0/4 Multicast address assignments
240.0.0.0/4 Reserved address space (including broadcast 255.255.255.255)

3. Port Restrictions

If the URL includes an explicit port number, wp_http_validate_url() checks it against an allowed list. By default, only three ports are permitted:

  • Port 80
  • Port 443
  • Port 8080

If the requested host matches the site’s configured home URL and uses the configured home port, that port is also accepted. Any other explicit destination port causes the function to return false.

Filter Hooks and Boundary Limitations

WordPress provides two filter hooks inside wp_http_validate_url() to adjust validation behavior:

http_request_host_is_external

apply_filters( 'http_request_host_is_external', bool $external, string $host, string $url )

When a host resolves to one of the reserved IPv4 ranges, this filter runs with $external set to false. Returning true allows the request to proceed. Because this bypasses private and loopback IP blocking, developers should scope callbacks strictly to expected hostnames or URLs rather than returning true globally, which would disable private IP protection across the site.

http_allowed_safe_ports

apply_filters( 'http_allowed_safe_ports', array( 80, 443, 8080 ), string $host, string $url )

This filter modifies the array of integer ports permitted by WordPress. Broadening the permitted ports allows requests to reach services running on alternate ports, so custom additions should be limited only to specific verified remote destinations.

Redirect Re-Validation

HTTP redirects can be leveraged to target internal addresses after providing an initial external URL. When reject_unsafe_urls is set to true by wp_safe_remote_get(), WordPress validates each redirected target URL via wp_http_validate_url() before making subsequent requests. If an external URL redirects to an address in a reserved IPv4 range (such as 127.0.0.1 or 169.254.169.254) or a disallowed port, the redirect chain is aborted.

Comparison of WordPress documented SSRF protections and validation boundaries

Text version of the diagrams

  • Safe GET vs URL Validator: Safe GET — Enables unsafe-URL rejection; URL checks — Validates scheme, host, port; Redirect checks — Revalidates each target
  • Protection Boundaries: IPv4 ranges — Blocks reserved destinations; Safe ports — Allows 80, 443, 8080; Boundaries — IPv6 and app controls remain

Research Method and Limitations

This article was prepared directly from public WordPress developer documentation excerpts for wp_http_validate_url() and wp_safe_remote_get() retrieved on 2026-09-17. Competing coverage was unavailable for comparison. The documented checks represent an IPv4-focused defensive mechanism rather than a complete SSRF mitigation strategy; the visible primary excerpts do not define IPv6 range filtering or higher-level application controls. Furthermore, custom filter callbacks can override these protections if not narrowly restricted.

Related guides