Make WordPress Core


Ignore:
Timestamp:
09/30/2024 05:17:54 AM (5 months ago)
Author:
peterwilsoncc
Message:

General: Remove noopener from links opening in a new tab.

Removes the automatic addition of rel="noopener noreferrer" from links targeting a new tab or window, target='_blank'. Since this was introduced, supported browsers have changed their security policies and no longer allow the opened link to have JavaScript access to the previous tab.

Deprecates:

  • wp_targeted_link_rel()
  • wp_targeted_link_rel_callback()
  • wp_init_targeted_link_rel_filters(): converted to a noop function
  • wp_remove_targeted_link_rel_filters(): converted to a noop function

The deprecated functions are retained in formatting.php as in SHORTINIT mode the file is included while deprecated.php is not.

This also removes the noopener from links hard coded within the WordPress dashboard linking to documentation and other resources.

Props audrasjb, azaozz, dhruval04, dorzki, neo2k23, presskopp, sabernhardt, swissspidy, tobiasbg.
Fixes #53843.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/formatting/wpTargetedLinkRel.php

    r56547 r59120  
    1 <?php
    2 
    3 /**
    4  * @group formatting
    5  * @ticket 43187
    6  *
    7  * @covers ::wp_targeted_link_rel
    8  */
    9 class Tests_Formatting_wpTargetedLinkRel extends WP_UnitTestCase {
    10 
    11     public function test_add_to_links_with_target_blank() {
    12         $content  = '<p>Links: <a href="/" target="_blank">No rel</a></p>';
    13         $expected = '<p>Links: <a href="/" target="_blank" rel="noopener">No rel</a></p>';
    14         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    15     }
    16 
    17     public function test_add_to_links_with_target_foo() {
    18         $content  = '<p>Links: <a href="/" target="foo">No rel</a></p>';
    19         $expected = '<p>Links: <a href="/" target="foo" rel="noopener">No rel</a></p>';
    20         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    21     }
    22 
    23     public function test_target_as_first_attribute() {
    24         $content  = '<p>Links: <a target="_blank" href="#">No rel</a></p>';
    25         $expected = '<p>Links: <a target="_blank" href="#" rel="noopener">No rel</a></p>';
    26         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    27     }
    28 
    29     public function test_add_to_existing_rel() {
    30         $content  = '<p>Links: <a href="/" rel="existing values" target="_blank">Existing rel</a></p>';
    31         $expected = '<p>Links: <a href="/" rel="existing values noopener" target="_blank">Existing rel</a></p>';
    32         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    33     }
    34 
    35     public function test_no_duplicate_values_added() {
    36         $content  = '<p>Links: <a href="/" rel="existing noopener values" target="_blank">Existing rel</a></p>';
    37         $expected = '<p>Links: <a href="/" rel="existing noopener values" target="_blank">Existing rel</a></p>';
    38         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    39     }
    40 
    41     public function test_rel_with_single_quote_delimiter() {
    42         $content  = '<p>Links: <a href="/" rel=\'existing values\' target="_blank">Existing rel</a></p>';
    43         $expected = '<p>Links: <a href="/" rel="existing values noopener" target="_blank">Existing rel</a></p>';
    44         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    45     }
    46 
    47     public function test_rel_with_no_delimiter() {
    48         $content  = '<p>Links: <a href="/" rel=existing target="_blank">Existing rel</a></p>';
    49         $expected = '<p>Links: <a href="/" rel="existing noopener" target="_blank">Existing rel</a></p>';
    50         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    51     }
    52 
    53     public function test_rel_value_spaced_and_no_delimiter() {
    54         $content  = '<p>Links: <a href="/" rel = existing target="_blank">Existing rel</a></p>';
    55         $expected = '<p>Links: <a href="/" rel="existing noopener" target="_blank">Existing rel</a></p>';
    56         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    57     }
    58 
    59     public function test_escaped_quotes() {
    60         $content  = '<p>Links: <a href=\"/\" rel=\"existing values\" target=\"_blank\">Existing rel</a></p>';
    61         $expected = '<p>Links: <a href=\"/\" rel=\"existing values noopener\" target=\"_blank\">Existing rel</a></p>';
    62         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    63     }
    64 
    65     public function test_ignore_links_with_no_target() {
    66         $content  = '<p>Links: <a href="/" target="_blank">Change me</a> <a href="/">Do not change me</a></p>';
    67         $expected = '<p>Links: <a href="/" target="_blank" rel="noopener">Change me</a> <a href="/">Do not change me</a></p>';
    68         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    69     }
    70 
    71     /**
    72      * Ensure empty rel attributes are not added.
    73      *
    74      * @ticket 45352
    75      */
    76     public function test_ignore_if_wp_targeted_link_rel_nulled() {
    77         add_filter( 'wp_targeted_link_rel', '__return_empty_string' );
    78         $content  = '<p>Links: <a href="/" target="_blank">Do not change me</a></p>';
    79         $expected = '<p>Links: <a href="/" target="_blank">Do not change me</a></p>';
    80         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    81     }
    82 
    83     /**
    84      * Ensure default content filters are added.
    85      *
    86      * @ticket 45292
    87      */
    88     public function test_wp_targeted_link_rel_filters_run() {
    89         $content  = '<p>Links: <a href="/" target="_blank">No rel</a></p>';
    90         $expected = '<p>Links: <a href="/" target="_blank" rel="noopener">No rel</a></p>';
    91 
    92         $post = self::factory()->post->create_and_get(
    93             array(
    94                 'post_content' => $content,
    95             )
    96         );
    97 
    98         $this->assertSame( $expected, $post->post_content );
    99     }
    100 
    101     /**
    102      * Ensure JSON format is preserved when relation attribute (rel) is missing.
    103      *
    104      * @ticket 46316
    105      */
    106     public function test_wp_targeted_link_rel_should_preserve_json() {
    107         $content  = '<p>Links: <a href=\"\/\" target=\"_blank\">No rel<\/a><\/p>';
    108         $expected = '<p>Links: <a href=\"\/\" target=\"_blank\" rel=\"noopener\">No rel<\/a><\/p>';
    109         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    110     }
    111 
    112     /**
    113      * Ensure the content of style and script tags are not processed
    114      *
    115      * @ticket 47244
    116      */
    117     public function test_wp_targeted_link_rel_skips_style_and_scripts() {
    118         $content  = '<style><a href="/" target=a></style><p>Links: <script>console.log("<a href=\'/\' target=a>hi</a>");</script><script>alert(1);</script>here <a href="/" target=_blank>aq</a></p><script>console.log("<a href=\'last\' target=\'_blank\'")</script>';
    119         $expected = '<style><a href="/" target=a></style><p>Links: <script>console.log("<a href=\'/\' target=a>hi</a>");</script><script>alert(1);</script>here <a href="/" target="_blank" rel="noopener">aq</a></p><script>console.log("<a href=\'last\' target=\'_blank\'")</script>';
    120         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    121     }
    122 
    123     /**
    124      * Ensure entirely serialized content is ignored.
    125      *
    126      * @ticket 46402
    127      */
    128     public function test_ignore_entirely_serialized_content() {
    129         $content  = 'a:1:{s:4:"html";s:52:"<p>Links: <a href="/" target="_blank">No Rel</a></p>";}';
    130         $expected = 'a:1:{s:4:"html";s:52:"<p>Links: <a href="/" target="_blank">No Rel</a></p>";}';
    131         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    132     }
    133 
    134     public function test_wp_targeted_link_rel_tab_separated_values_are_split() {
    135         $content  = "<p>Links: <a href=\"/\" target=\"_blank\" rel=\"ugc\t\tnoopener\t\">No rel</a></p>";
    136         $expected = '<p>Links: <a href="/" target="_blank" rel="ugc noopener">No rel</a></p>';
    137         $this->assertSame( $expected, wp_targeted_link_rel( $content ) );
    138     }
    139 }
Note: See TracChangeset for help on using the changeset viewer.