Make WordPress Core

Changeset 63115


Ignore:
Timestamp:
08/06/2026 07:59:05 PM (5 weeks ago)
Author:
desrosj
Message:

Security: Backport the WordPress 7.0.3 security fixes to the 4.7 branch.

  • Users: Ensure a proper email address is used before sending email confirmations.
  • Formatting: Prevent stack overflow in safecss_filter_attr.
  • Multisite: Enforce the active signup policy for existing users.
  • HTTP API: Improve compliance with IPv4 Special-Purpose Address Space.
  • Users: Prevent Usernames from mangling HTML
  • Canonical: Only redirect for publicly viewable post types.
  • Administration: When wp_is_large_user_count(), ensure that the post author is always added to author dropdown.

Merges [63065],[63063],[63064],[63062],[63067],[63060],[63061] to the 4.7 branch.

Props xknown, westonruter, jeremyfelt, peterwilsoncc, paulkevan, lucasbustamante, jorbin, desrosj, vortfu, dmsnell, johnbillion, ehtis, batmoo, lancewillett, jonsurrell.

Location:
branches/4.7/src
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • branches/4.7/src/wp-admin/includes/ms.php

    r49399 r63115  
    331331 * @since 3.0.0
    332332 *
     333 * @param int $user_id Optional. The ID of the user whose email is being changed. Defaults to `$_POST['user_id']` if set, otherwise 0.
     334 *
    333335 * @global WP_Error $errors WP_Error object.
    334336 * @global wpdb     $wpdb   WordPress database object.
    335337 */
    336 function send_confirmation_on_profile_email() {
     338function send_confirmation_on_profile_email( $user_id = 0 ) {
    337339        global $errors, $wpdb;
     340
     341        // Maintain backward compatibility for those relying on a check based on $_POST['user_id'].
     342        if ( ! $user_id && isset( $_POST['user_id'] ) ) {
     343                $user_id = (int) $_POST['user_id'];
     344        }
     345
    338346        $current_user = wp_get_current_user();
    339347        if ( ! is_object($errors) )
    340348                $errors = new WP_Error();
    341349
    342         if ( $current_user->ID != $_POST['user_id'] )
     350        if ( 0 === $current_user->ID || $current_user->ID !== (int) $user_id )
    343351                return false;
    344352
     
    346354                if ( !is_email( $_POST['email'] ) ) {
    347355                        $errors->add( 'user_email', __( "<strong>ERROR</strong>: The email address isn&#8217;t correct." ), array( 'form-field' => 'email' ) );
     356                        $_POST['email'] = addslashes( $current_user->user_email );
    348357                        return;
    349358                }
     
    352361                        $errors->add( 'user_email', __( "<strong>ERROR</strong>: The email address is already used." ), array( 'form-field' => 'email' ) );
    353362                        delete_user_meta( $current_user->ID, '_new_email' );
     363                        $_POST['email'] = addslashes( $current_user->user_email );
    354364                        return;
    355365                }
  • branches/4.7/src/wp-admin/includes/user.php

    r39269 r63115  
    4343                $user->user_login = sanitize_user($_POST['user_login'], true);
    4444
     45        $errors = new WP_Error();
     46
    4547        $pass1 = $pass2 = '';
    4648        if ( isset( $_POST['pass1'] ) )
     
    6365        }
    6466
    65         if ( isset( $_POST['email'] ))
    66                 $user->user_email = sanitize_text_field( wp_unslash( $_POST['email'] ) );
     67        if ( isset( $_POST['email'] ) ) {
     68                $maybe_email = wp_unslash( $_POST['email'] );
     69                if ( is_string( $maybe_email ) && is_email( $maybe_email ) ) {
     70                        $user->user_email = $maybe_email;
     71                } else {
     72                        $errors->add( 'invalid_email', __( '<strong>ERROR</strong>: The email address isn&#8217;t correct.' ), array( 'form-field' => 'email' ) );
     73                }
     74        }
    6775        if ( isset( $_POST['url'] ) ) {
    6876                if ( empty ( $_POST['url'] ) || $_POST['url'] == 'http://' ) {
     
    116124        if ( !empty($_POST['use_ssl']) )
    117125                $user->use_ssl = 1;
    118 
    119         $errors = new WP_Error();
    120126
    121127        /* checking that username has been typed */
  • branches/4.7/src/wp-admin/js/inline-edit-post.js

    r40365 r63115  
    154154                if ( !$(':input[name="post_author"] option[value="' + $('.post_author', rowData).text() + '"]', editRow).val() ) {
    155155                        // author no longer has edit caps, so we need to add them to the list of authors
    156                         $(':input[name="post_author"]', editRow).prepend('<option value="' + $('.post_author', rowData).text() + '">' + $('#' + t.type + '-' + id + ' .author').text() + '</option>');
     156                        $(':input[name="post_author"]', editRow).prepend(
     157                                new Option(
     158                                        $('#' + t.type + '-' + id + ' .author').text(),
     159                                        $('.post_author', rowData).text()
     160                                )
     161                        );
    157162                }
    158163                if ( $( ':input[name="post_author"] option', editRow ).length === 1 ) {
  • branches/4.7/src/wp-includes/canonical.php

    r38216 r63115  
    590590
    591591        if ( get_query_var('name') ) {
     592                $publicly_viewable_post_types = array_filter( get_post_types( array( 'exclude_from_search' => false ) ), 'is_post_type_viewable' );
     593
    592594                $where = $wpdb->prepare("post_name LIKE %s", $wpdb->esc_like( get_query_var('name') ) . '%');
    593595
    594596                // if any of post_type, year, monthnum, or day are set, use them to refine the query
    595                 if ( get_query_var('post_type') )
    596                         $where .= $wpdb->prepare(" AND post_type = %s", get_query_var('post_type'));
    597                 else
    598                         $where .= " AND post_type IN ('" . implode( "', '", get_post_types( array( 'public' => true ) ) ) . "')";
     597                if ( get_query_var( 'post_type' ) ) {
     598                        if ( is_array( get_query_var( 'post_type' ) ) ) {
     599                                $post_types = array_intersect( get_query_var( 'post_type' ), $publicly_viewable_post_types );
     600                                if ( empty( $post_types ) ) {
     601                                        return false;
     602                                }
     603                                $where .= " AND post_type IN ('" . implode( "', '", esc_sql( $post_types ) ) . "')";
     604                        } else {
     605                                if ( ! in_array( get_query_var( 'post_type' ), $publicly_viewable_post_types, true ) ) {
     606                                        return false;
     607                                }
     608                                $where .= $wpdb->prepare( ' AND post_type = %s', get_query_var( 'post_type' ) );
     609                        }
     610                } else {
     611                        $where .= " AND post_type IN ('" . implode( "', '", esc_sql( $publicly_viewable_post_types ) ) . "')";
     612                }
    599613
    600614                if ( get_query_var('year') )
  • branches/4.7/src/wp-includes/http.php

    r46495 r63115  
    548548                if ( $ip ) {
    549549                        $parts = array_map( 'intval', explode( '.', $ip ) );
    550                         if ( 127 === $parts[0] || 10 === $parts[0] || 0 === $parts[0]
    551                                 || ( 172 === $parts[0] && 16 <= $parts[1] && 31 >= $parts[1] )
    552                                 || ( 192 === $parts[0] && 168 === $parts[1] )
     550
     551                        /*
     552                         * These IP address ranges are not considered valid external hosts for HTTP requests.
     553                         *
     554                         * If the host resolves to an IP address in these ranges, the request will be rejected unless the 'http_request_host_is_external' filter allows it.
     555                         *
     556                         * References:
     557                         *
     558                         * - IPv4 Special-Purpose Address Space: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
     559                         * - IPv4 Multicast Address Assignments: https://www.rfc-editor.org/rfc/rfc5771.html
     560                         */
     561                        if ( 127 === $parts[0] || 10 === $parts[0] || 0 === $parts[0]          // 127.0.0.0/8 (loopback), 10.0.0.0/8 (private), 0.0.0.0/8 (this network).
     562                                || ( 172 === $parts[0] && 16 <= $parts[1] && 31 >= $parts[1] )     // 172.16.0.0/12 (private).
     563                                || ( 192 === $parts[0] && 168 === $parts[1] )                      // 192.168.0.0/16 (private).
     564                                || ( 192 === $parts[0] && 0 === $parts[1] && 0 === $parts[2] )     // 192.0.0.0/24 (IETF protocol assignments).
     565                                || ( 192 === $parts[0] && 0 === $parts[1] && 2 === $parts[2] )     // 192.0.2.0/24 (TEST-NET-1).
     566                                || ( 192 === $parts[0] && 88 === $parts[1] && 99 === $parts[2] )   // 192.88.99.0/24 (6to4 relay anycast).
     567                                || ( 198 === $parts[0] && 51 === $parts[1] && 100 === $parts[2] )  // 198.51.100.0/24 (TEST-NET-2).
     568                                || ( 203 === $parts[0] && 0 === $parts[1] && 113 === $parts[2] )   // 203.0.113.0/24 (TEST-NET-3).
     569                                || ( 169 === $parts[0] && 254 === $parts[1] )                      // 169.254.0.0/16 (link-local and cloud metadata).
     570                                || ( 100 === $parts[0] && 64 <= $parts[1] && 127 >= $parts[1] )    // 100.64.0.0/10 (CGNAT).
     571                                || ( 198 === $parts[0] && 18 <= $parts[1] && 19 >= $parts[1] )     // 198.18.0.0/15 (benchmarking).
     572                                || ( 224 <= $parts[0] && 239 >= $parts[0] )                        // 224.0.0.0/4 (multicast).
     573                                || 240 <= $parts[0]                                                // 240.0.0.0/4 (reserved, includes 255.255.255.255 broadcast).
    553574                        ) {
    554575                                // If host appears local, reject unless specifically allowed.
  • branches/4.7/src/wp-includes/kses.php

    r62006 r63115  
    17481748        $css = str_replace(array("\n","\r","\t"), '', $css);
    17491749
    1750         if ( preg_match( '%[\\\\(&=}]|/\*%', $css ) ) // remove any inline css containing \ ( & } = or comments
     1750        if ( 0 !== preg_match( '%[\\\\(&=}]|/\*%', $css ) ) // remove any inline css containing \ ( & } = or comments
    17511751                return '';
    17521752
  • branches/4.7/src/wp-includes/user.php

    r47650 r63115  
    165165                                /* translators: %s: user name */
    166166                                __( '<strong>ERROR</strong>: The password you entered for the username %s is incorrect.' ),
    167                                 '<strong>' . $username . '</strong>'
     167                                '<strong>' . esc_html( $username ) . '</strong>'
    168168                        ) .
    169169                        ' <a href="' . wp_lostpassword_url() . '">' .
     
    237237                                /* translators: %s: email address */
    238238                                __( '<strong>ERROR</strong>: The password you entered for the email address %s is incorrect.' ),
    239                                 '<strong>' . $email . '</strong>'
     239                                '<strong>' . esc_html( $email ) . '</strong>'
    240240                        ) .
    241241                        ' <a href="' . wp_lostpassword_url() . '">' .
     
    23392339        $user_id = wp_create_user( $sanitized_user_login, $user_pass, $user_email );
    23402340        if ( ! $user_id || is_wp_error( $user_id ) ) {
    2341                 $errors->add( 'registerfail', sprintf( __( '<strong>ERROR</strong>: Couldn&#8217;t register you&hellip; please contact the <a href="mailto:%s">webmaster</a> !' ), get_option( 'admin_email' ) ) );
     2341                $errors->add( 'registerfail', sprintf( __( '<strong>ERROR</strong>: Couldn&#8217;t register you&hellip; please contact the <a href="mailto:%s">webmaster</a> !' ), esc_attr( get_option( 'admin_email' ) ) ) );
    23422342                return $errors;
    23432343        }
  • branches/4.7/src/wp-signup.php

    r38814 r63115  
    853853                        break;
    854854                case 'gimmeanotherblog':
    855                         validate_another_blog_signup();
     855                        if ( 'all' === $active_signup || 'blog' === $active_signup ) {
     856                                validate_another_blog_signup();
     857                        } else {
     858                                _e( 'Site registration has been disabled.' );
     859                        }
    856860                        break;
    857861                case 'default':
Note: See TracChangeset for help on using the changeset viewer.