| @@ -609,10 +609,11 @@ | ||
| 609 | 609 | public function validate_sitemap(WP_REST_Request $request) { |
| 610 | 610 | try { |
| 611 | 611 | $sitemap_url = $request->get_param('sitemap_url') ?? home_url('/sitemap.xml'); |
| 612 | 612 | |
| 613 | - // Validate sitemap URL | |
| 614 | - if (!filter_var($sitemap_url, FILTER_VALIDATE_URL)) { | |
| 613 | + // Validate sitemap URL. Url_Validator accepts an internationalised | |
| 614 | + // domain or a non-ASCII path (home_url() on an IDN site is one). | |
| 615 | + if (!\ThinkRank\Core\Url_Validator::is_valid($sitemap_url)) { | |
| 615 | 616 | return new WP_Error( |
| 616 | 617 | 'invalid_url', |
| 617 | 618 | 'Invalid sitemap URL provided', |
| 618 | 619 | ['status' => 400] |
| @@ -617,8 +618,14 @@ | ||
| 617 | 618 | 'Invalid sitemap URL provided', |
| 618 | 619 | ['status' => 400] |
| 619 | 620 | ); |
| 620 | 621 | } |
| 622 | + | |
| 623 | + // Everything from here on works on the ASCII form (punycode host, | |
| 624 | + // percent-encoded path). wp_http_validate_url() resolves the host | |
| 625 | + // with gethostbyname(), which cannot resolve a Unicode name, and | |
| 626 | + // the SSRF check must see exactly the URL that is fetched. | |
| 627 | + $sitemap_url = \ThinkRank\Core\Url_Validator::to_ascii((string) $sitemap_url); | |
| 621 | 628 | |
| 622 | 629 | // Block SSRF: this endpoint fetches the URL server-side, so reject |
| 623 | 630 | // loopback/link-local/private hosts and non-http(s) schemes via |
| 624 | 631 | // WordPress's own validator (same guard used in class-schema-endpoint). |