Skip to content

Instantly share code, notes, and snippets.

@afragen
Last active March 19, 2026 22:20
Show Gist options
  • Select an option

  • Save afragen/ece38aafd57634b49e428c23baa2d551 to your computer and use it in GitHub Desktop.

Select an option

Save afragen/ece38aafd57634b49e428c23baa2d551 to your computer and use it in GitHub Desktop.
WordPress function to check if URL is SSRF safe.
<?php
function is_url_ssrf_safe( $url ) {
$allowed_protocols = [ 'http', 'https' ];
$scheme = parse_url( $url, PHP_URL_SCHEME );
if ( ! in_array( $scheme, $allowed_protocols, true ) ) {
return new WP_Error( 'invalid_protocol', __( 'The URL provided uses an unsupported protocol.', 'textdomain' ) );
}
$ip = gethostbyname( parse_url( $url, PHP_URL_HOST ) );
if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) === false ) {
return new WP_Error( 'private_ip', __( 'The URL provided resolves to a private or reserved IP address.', 'textdomain' ) );
}
if ( ! filter_var( $url, FILTER_SANITIZE_URL ) || ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
return new WP_Error( 'invalid_url', __( 'The URL provided is not valid.', 'textdomain' ) );
}
return true;
}
<?php
// AI generated.
function isSafeUrl($url) {
// 1. Validate structure
if (!filter_var($url, FILTER_VALIDATE_URL)) return false;
$parts = parse_url($url);
// 2. Restrict Schemes
if (!in_array($parts['scheme'], ['http', 'https'])) return false;
// 3. Allowlist Host
$allowedHosts = ['example.com', 'api.example.com'];
if (!in_array($parts['host'], $allowedHosts)) return false;
// 4. Block Local/Internal IP Addresses
$ip = gethostbyname($parts['host']);
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
return false;
}
return true;
}
// AI generated without allow|block lists.
function isUrlSafe($url) {
// 1. Validate URL format
if (!filter_var($url, FILTER_VALIDATE_URL)) return false;
$parts = parse_url($url);
// 2. Enforce HTTPS only
if ($parts['scheme'] !== 'https') return false;
// 3. Get IP address of the host
$host = $parts['host'];
$ip = gethostbyname($host);
// 4. Validate IP is not private/local (SSRF Protection)
// filter_var with FILTER_FLAG_NO_PRIV_RANGE and FILTER_FLAG_NO_RES_RANGE
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
return false; // Host resolves to a private/internal IP
}
return true;
}
// Usage
$userUrl = $_POST['url'];
if (isUrlSafe($userUrl)) {
// Fetch content
$content = file_get_contents($userUrl);
} else {
die("Invalid or prohibited URL");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment