Make WordPress Core

Changeset 63307 for trunk


Ignore:
Timestamp:
08/16/2026 04:55:59 PM (3 weeks ago)
Author:
joedolson
Message:

Rewrite Rules: Only a leading www. is optional in url_to_postid().

Fixes the behavior of url_to_postid(), which treated a www. string anywhere in the URL as optional, breaking some URLs. Anchor the string so that is only considered optional when at the beginning of a URL string.

Follow up to [63207].

Props youknowriad, johnbillion, wildworks, irozum, joedolson.
Fixes #65016.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rewrite.php

    r61444 r63307  
    503503
    504504        if ( is_string( $url_host ) ) {
    505                 $url_host = str_replace( 'www.', '', $url_host );
     505                // Only a leading 'www.' is optional. Removing it anywhere else would match a different host.
     506                $url_host = preg_replace( '|^www\.|', '', $url_host );
    506507        } else {
    507508                $url_host = '';
     
    511512
    512513        if ( is_string( $home_url_host ) ) {
    513                 $home_url_host = str_replace( 'www.', '', $home_url_host );
     514                $home_url_host = preg_replace( '|^www\.|', '', $home_url_host );
    514515        } else {
    515516                $home_url_host = '';
  • trunk/tests/phpunit/tests/rewrite.php

    r62957 r63307  
    264264
    265265        /**
     266         * Only a leading 'www.' is optional when comparing the URL's host to the site's.
     267         *
     268         * A 'www.' elsewhere in the host belongs to a different domain, which an attacker
     269         * can register: stripping it everywhere makes 'exwww.ample.com' match 'example.com'.
     270         *
     271         * @ticket 65016
     272         *
     273         * @covers ::url_to_postid
     274         *
     275         * @dataProvider data_url_to_postid_host_matching
     276         *
     277         * @param string $host     Host of the URL to resolve.
     278         * @param bool   $is_local Whether the host should be treated as this site.
     279         */
     280        public function test_url_to_postid_matches_www_prefix_only( $host, $is_local ) {
     281                update_option( 'home', 'https://example.com' );
     282                update_option( 'siteurl', 'https://example.com' );
     283
     284                $post_id = self::factory()->post->create();
     285
     286                $expected = $is_local ? $post_id : 0;
     287
     288                $this->assertSame( $expected, url_to_postid( "https://$host/?p=$post_id" ) );
     289        }
     290
     291        /**
     292         * Data provider.
     293         *
     294         * @return array[]
     295         */
     296        public function data_url_to_postid_host_matching() {
     297                return array(
     298                        'the site host'              => array( 'example.com', true ),
     299                        'the site host with www'     => array( 'www.example.com', true ),
     300                        'www inside the domain'      => array( 'exwww.ample.com', false ),
     301                        'www inside the TLD'         => array( 'example.cwww.om', false ),
     302                        'an unrelated host'          => array( 'evil.com', false ),
     303                        'the site host as subdomain' => array( 'example.com.evil.com', false ),
     304                );
     305        }
     306
     307        /**
    266308         * @covers ::url_to_postid
    267309         */
Note: See TracChangeset for help on using the changeset viewer.