WordPress.org

Make WordPress Core

Changeset 42770


Ignore:
Timestamp:
03/02/2018 02:41:04 PM (20 months ago)
Author:
azaozz
Message:

Add pre-save content filter to make target=_blank always secure.

Props notnownikki, iseulde, azaozz
Fixes #43187

Location:
trunk
Files:
1 added
4 edited

Legend:

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

    r42441 r42770  
    104104    add_filter( $filter, 'balanceTags', 50 );
    105105}
     106
     107// Add proper rel values for links with target.
     108foreach ( array(
     109    'title_save_pre',
     110    'content_save_pre',
     111    'excerpt_save_pre',
     112    'content_filtered_save_pre',
     113    'pre_comment_content',
     114    'pre_term_description',
     115    'pre_link_description',
     116    'pre_link_notes',
     117    'pre_user_description',
     118) as $filter ) {
     119    add_filter( $filter, 'wp_targeted_link_rel' );
     120};
    106121
    107122// Format strings for display.
  • trunk/src/wp-includes/formatting.php

    r42610 r42770  
    30253025
    30263026/**
     3027 * Adds rel noreferrer and noopener to all HTML A elements that have a target.
     3028 *
     3029 * @param string $text Content that may contain HTML A elements.
     3030 * @return string Converted content.
     3031 */
     3032function wp_targeted_link_rel( $text ) {
     3033    // Don't run (more expensive) regex if no links with targets.
     3034    if ( stripos( $text, 'target' ) !== false && stripos( $text, '<a ' ) !== false ) {
     3035        $text = preg_replace_callback( '|<a\s([^>]*target\s*=[^>]*)>|i', 'wp_targeted_link_rel_callback', $text );
     3036    }
     3037
     3038    return $text;
     3039}
     3040
     3041/**
     3042 * Callback to add rel="noreferrer noopener" string to HTML A element.
     3043 *
     3044 * Will not duplicate existing noreferrer and noopener values
     3045 * to prevent from invalidating the HTML.
     3046 *
     3047 * @param array $matches Single Match
     3048 * @return string HTML A Element with rel noreferrer noopener in addition to any existing values
     3049 */
     3050function wp_targeted_link_rel_callback( $matches ) {
     3051    $link_html = $matches[1];
     3052    $rel_match = array();
     3053
     3054    /**
     3055     * Filters the rel values that are added to links with `target` attribute.
     3056     *
     3057     * @since 5.0.0
     3058     *
     3059     * @param string The rel values.
     3060     * @param string $link_html The matched content of the link tag including all HTML attributes.
     3061     */
     3062    $rel = apply_filters( 'wp_targeted_link_rel', 'noopener noreferrer', $link_html );
     3063
     3064    // Value with delimiters, spaces around are optional.
     3065    $attr_regex = '|rel\s*=\s*?(\\\\{0,1}["\'])(.*?)\\1|i';
     3066    preg_match( $attr_regex, $link_html, $rel_match );
     3067
     3068    if ( empty( $rel_match[0] ) ) {
     3069        // No delimiters, try with a single value and spaces, because `rel =  va"lue` is totally fine...
     3070        $attr_regex = '|rel\s*=(\s*)([^\s]*)|i';
     3071        preg_match( $attr_regex, $link_html, $rel_match );
     3072    }
     3073
     3074    if ( ! empty( $rel_match[0] ) ) {
     3075        $parts = preg_split( '|\s+|', strtolower( $rel_match[2] ) );
     3076        $parts = array_map( 'esc_attr', $parts );
     3077        $needed = explode( ' ', $rel );
     3078        $parts = array_unique( array_merge( $parts, $needed ) );
     3079        $delimiter = trim( $rel_match[1] ) ? $rel_match[1] : '"';
     3080        $rel = 'rel=' . $delimiter . trim( implode( ' ', $parts ) ) . $delimiter;
     3081        $link_html = str_replace( $rel_match[0], $rel, $link_html );
     3082    } else {
     3083        $link_html .= " rel=\"$rel\"";
     3084    }
     3085
     3086    return "<a $link_html>";
     3087}
     3088
     3089/**
    30273090 * Convert one smiley code to the icon graphic file equivalent.
    30283091 *
  • trunk/tests/phpunit/tests/rest-api/rest-attachments-controller.php

    r42724 r42770  
    10161016                    ),
    10171017                    'description' => array(
    1018                         'raw'      => '<a href="#" target="_blank">link</a>',
    1019                         'rendered' => '<p><a href="#" target="_blank">link</a></p>',
     1018                        'raw'      => '<a href="#" target="_blank" rel="noopener noreferrer">link</a>',
     1019                        'rendered' => '<p><a href="#" target="_blank" rel="noopener noreferrer">link</a></p>',
    10201020                    ),
    10211021                    'caption'     => array(
    1022                         'raw'      => '<a href="#" target="_blank">link</a>',
    1023                         'rendered' => '<p><a href="#" target="_blank">link</a></p>',
     1022                        'raw'      => '<a href="#" target="_blank" rel="noopener noreferrer">link</a>',
     1023                        'rendered' => '<p><a href="#" target="_blank" rel="noopener noreferrer">link</a></p>',
    10241024                    ),
    10251025                ),
  • trunk/tests/phpunit/tests/rest-api/rest-posts-controller.php

    r42724 r42770  
    31863186                    ),
    31873187                    'content' => array(
    3188                         'raw'      => '<a href="#" target="_blank">link</a>',
    3189                         'rendered' => '<p><a href="#" target="_blank">link</a></p>',
     3188                        'raw'      => '<a href="#" target="_blank" rel="noopener noreferrer">link</a>',
     3189                        'rendered' => '<p><a href="#" target="_blank" rel="noopener noreferrer">link</a></p>',
    31903190                    ),
    31913191                    'excerpt' => array(
    3192                         'raw'      => '<a href="#" target="_blank">link</a>',
    3193                         'rendered' => '<p><a href="#" target="_blank">link</a></p>',
     3192                        'raw'      => '<a href="#" target="_blank" rel="noopener noreferrer">link</a>',
     3193                        'rendered' => '<p><a href="#" target="_blank" rel="noopener noreferrer">link</a></p>',
    31943194                    ),
    31953195                ),
Note: See TracChangeset for help on using the changeset viewer.