WordPress.org

Make WordPress Core

Changeset 38890


Ignore:
Timestamp:
10/24/2016 08:06:06 PM (3 years ago)
Author:
westonruter
Message:

Customize: Harden url matching to account for varying ports and ensuring matching base pathname for allowed urls

Fixes #38409.

Location:
trunk/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/js/customize-controls.js

    r38889 r38890  
    40414041
    40424042            previewer.add( 'previewUrl', params.previewUrl ).setter( function( to ) {
    4043                 var result, urlParser, newPreviewUrl, schemeMatchingPreviewUrl, queryParams;
     4043                var result = null, urlParser, queryParams, parsedAllowedUrl, parsedCandidateUrls = [];
    40444044                urlParser = document.createElement( 'a' );
    40454045                urlParser.href = to;
     
    40634063                }
    40644064
    4065                 newPreviewUrl = urlParser.href;
    4066                 urlParser.protocol = previewer.scheme.get() + ':';
    4067                 schemeMatchingPreviewUrl = urlParser.href;
     4065                parsedCandidateUrls.push( urlParser );
     4066
     4067                // Prepend list with URL that matches the scheme/protocol of the iframe.
     4068                if ( previewer.scheme.get() + ':' !== urlParser.protocol ) {
     4069                    urlParser = document.createElement( 'a' );
     4070                    urlParser.href = parsedCandidateUrls[0].href;
     4071                    urlParser.protocol = previewer.scheme.get() + ':';
     4072                    parsedCandidateUrls.unshift( urlParser );
     4073                }
    40684074
    40694075                // Attempt to match the URL to the control frame's scheme
    40704076                // and check if it's allowed. If not, try the original URL.
    4071                 $.each( [ schemeMatchingPreviewUrl, newPreviewUrl ], function( i, url ) {
    4072                     $.each( previewer.allowedUrls, function( i, allowed ) {
    4073                         var path;
    4074 
    4075                         allowed = allowed.replace( /\/+$/, '' );
    4076                         path = url.replace( allowed, '' );
    4077 
    4078                         if ( 0 === url.indexOf( allowed ) && /^([/#?]|$)/.test( path ) ) {
    4079                             result = url;
    4080                             return false;
     4077                parsedAllowedUrl = document.createElement( 'a' );
     4078                _.find( parsedCandidateUrls, function( parsedCandidateUrl ) {
     4079                    return ! _.isUndefined( _.find( previewer.allowedUrls, function( allowedUrl ) {
     4080                        parsedAllowedUrl.href = allowedUrl;
     4081                        if ( urlParser.protocol === parsedAllowedUrl.protocol && urlParser.host === parsedAllowedUrl.host && 0 === parsedAllowedUrl.pathname.indexOf( urlParser.pathname ) ) {
     4082                            result = parsedCandidateUrl.href;
     4083                            return true;
    40814084                        }
    4082                     });
    4083                     if ( result ) {
    4084                         return false;
    4085                     }
    4086                 });
    4087 
    4088                 // If we found a matching result, return it. If not, bail.
    4089                 return result ? result : null;
     4085                    } ) );
     4086                } );
     4087
     4088                return result;
    40904089            });
    40914090
  • trunk/src/wp-includes/js/customize-base.js

    r38810 r38890  
    655655                var urlParser = document.createElement( 'a' );
    656656                urlParser.href = to;
    657                 return urlParser.protocol + '//' + urlParser.hostname;
     657                // Port stripping needed by IE since it adds to host but not to event.origin.
     658                return urlParser.protocol + '//' + urlParser.host.replace( /:80$/, '' );
    658659            });
    659660
  • trunk/src/wp-includes/js/customize-preview.js

    r38829 r38890  
    276276     * @param {string} element.search Query string.
    277277     * @param {string} element.pathname Path.
    278      * @param {string} element.hostname Hostname.
     278     * @param {string} element.host Host.
    279279     * @param {object} [options]
    280280     * @param {object} [options.allowAdminAjax=false] Allow admin-ajax.php requests.
     
    282282     */
    283283    api.isLinkPreviewable = function isLinkPreviewable( element, options ) {
    284         var hasMatchingHost, urlParser, args;
     284        var matchesAllowedUrl, parsedAllowedUrl, args;
    285285
    286286        args = _.extend( {}, { allowAdminAjax: false }, options || {} );
     
    295295        }
    296296
    297         urlParser = document.createElement( 'a' );
    298         hasMatchingHost = ! _.isUndefined( _.find( api.settings.url.allowed, function( allowedUrl ) {
    299             urlParser.href = allowedUrl;
    300             if ( urlParser.hostname === element.hostname && urlParser.protocol === element.protocol ) {
    301                 return true;
    302             }
    303             return false;
     297        parsedAllowedUrl = document.createElement( 'a' );
     298        matchesAllowedUrl = ! _.isUndefined( _.find( api.settings.url.allowed, function( allowedUrl ) {
     299            parsedAllowedUrl.href = allowedUrl;
     300            return parsedAllowedUrl.protocol === element.protocol && parsedAllowedUrl.host === element.host && 0 === element.pathname.indexOf( parsedAllowedUrl.pathname );
    304301        } ) );
    305         if ( ! hasMatchingHost ) {
     302        if ( ! matchesAllowedUrl ) {
    306303            return false;
    307304        }
     
    332329     *
    333330     * @param {HTMLAnchorElement|HTMLAreaElement} element Link element.
    334      * @param {object} element.search Query string.
     331     * @param {string} element.search Query string.
     332     * @param {string} element.host Host.
     333     * @param {string} element.protocol Protocol.
    335334     * @returns {void}
    336335     */
     
    349348
    350349        // Make sure links in preview use HTTPS if parent frame uses HTTPS.
    351         if ( 'https' === api.preview.scheme.get() && 'http:' === element.protocol && -1 !== api.settings.url.allowedHosts.indexOf( element.hostname ) ) {
     350        if ( 'https' === api.preview.scheme.get() && 'http:' === element.protocol && -1 !== api.settings.url.allowedHosts.indexOf( element.host ) ) {
    352351            element.protocol = 'https:';
    353352        }
     
    497496
    498497        // Make sure forms in preview use HTTPS if parent frame uses HTTPS.
    499         if ( 'https' === api.preview.scheme.get() && 'http:' === urlParser.protocol && -1 !== api.settings.url.allowedHosts.indexOf( urlParser.hostname ) ) {
     498        if ( 'https' === api.preview.scheme.get() && 'http:' === urlParser.protocol && -1 !== api.settings.url.allowedHosts.indexOf( urlParser.host ) ) {
    500499            urlParser.protocol = 'https:';
    501500            form.action = urlParser.href;
Note: See TracChangeset for help on using the changeset viewer.