Make WordPress Core

Changeset 52304


Ignore:
Timestamp:
12/02/2021 12:54:03 AM (3 years ago)
Author:
peterwilsoncc
Message:

KSES: Allow attributes to be restricted via callbacks.

Add callback validation to HTML tag attributes for increased flexibility over an array of values only.

In object tags, validate the data attribute via a callback to ensure it is a PDF and matches the type attribute. This prevents mime type mismatches in browsers.

Follow up to [51963].

Props Pento, dd32, swissspidy, xknown, peterwilsoncc.
Fixes #54261.

Location:
trunk
Files:
2 edited

Legend:

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

    r52234 r52304  
    273273        ),
    274274        'object'     => array(
    275             'data' => true,
     275            'data' => array(
     276                'required'       => true,
     277                'value_callback' => '_wp_kses_allow_pdf_objects',
     278            ),
    276279            'type' => array(
    277280                'required' => true,
     
    16621665            }
    16631666            break;
     1667
     1668        case 'value_callback':
     1669            /*
     1670             * The value_callback check is used when you want to make sure that the attribute
     1671             * value is accepted by the callback function.
     1672             */
     1673
     1674            if ( ! call_user_func( $checkvalue, $value ) ) {
     1675                $ok = false;
     1676            }
     1677            break;
    16641678    } // End switch.
    16651679
     
    25672581    return $value;
    25682582}
     2583
     2584/**
     2585 * Helper function to check if this is a safe PDF URL.
     2586 *
     2587 * @since 5.9.0
     2588 * @access private
     2589 * @ignore
     2590 *
     2591 * @param string $url The URL to check.
     2592 * @return bool True if the URL is safe, false otherwise.
     2593 */
     2594function _wp_kses_allow_pdf_objects( $value ) {
     2595    // We're not interested in URLs that contain query strings or fragments.
     2596    if ( strpos( $value, '?' ) !== false || strpos( $value, '#' ) !== false ) {
     2597        return false;
     2598    }
     2599
     2600    // If it doesn't have a PDF extension, it's not safe.
     2601    if ( 0 !== substr_compare( $value, '.pdf', -4, 4, true ) ) {
     2602        return false;
     2603    }
     2604
     2605    // If the URL host matches the current site's media URL, it's safe.
     2606    $upload_info = wp_upload_dir( null, false );
     2607    $upload_host = wp_parse_url( $upload_info['url'], PHP_URL_HOST );
     2608    if ( 0 === strpos( $value, "http://$upload_host/" ) || 0 === strpos( $value, "https://$upload_host/" ) ) {
     2609        return true;
     2610    }
     2611
     2612    return false;
     2613}
  • trunk/tests/phpunit/tests/kses.php

    r52229 r52304  
    15181518        return array(
    15191519            'valid value for type'                    => array(
    1520                 '<object type="application/pdf" data="https://wordpress.org/foo.pdf" />',
    1521                 '<object type="application/pdf" data="https://wordpress.org/foo.pdf" />',
     1520                '<object type="application/pdf" data="https://example.org/foo.pdf" />',
     1521                '<object type="application/pdf" data="https://example.org/foo.pdf" />',
    15221522            ),
    15231523            'invalid value for type'                  => array(
    1524                 '<object type="application/exe" data="https://wordpress.org/foo.exe" />',
     1524                '<object type="application/exe" data="https://example.org/foo.exe" />',
    15251525                '',
    15261526            ),
    15271527            'multiple type attributes, last invalid'  => array(
    1528                 '<object type="application/pdf" type="application/exe" data="https://wordpress.org/foo.pdf" />',
    1529                 '<object type="application/pdf" data="https://wordpress.org/foo.pdf" />',
     1528                '<object type="application/pdf" type="application/exe" data="https://example.org/foo.pdf" />',
     1529                '<object type="application/pdf" data="https://example.org/foo.pdf" />',
    15301530            ),
    15311531            'multiple type attributes, first uppercase, last invalid' => array(
    1532                 '<object TYPE="application/pdf" type="application/exe" data="https://wordpress.org/foo.pdf" />',
    1533                 '<object TYPE="application/pdf" data="https://wordpress.org/foo.pdf" />',
     1532                '<object TYPE="application/pdf" type="application/exe" data="https://example.org/foo.pdf" />',
     1533                '<object TYPE="application/pdf" data="https://example.org/foo.pdf" />',
    15341534            ),
    15351535            'multiple type attributes, last upper case and invalid' => array(
    1536                 '<object type="application/pdf" TYPE="application/exe" data="https://wordpress.org/foo.pdf" />',
    1537                 '<object type="application/pdf" data="https://wordpress.org/foo.pdf" />',
     1536                '<object type="application/pdf" TYPE="application/exe" data="https://example.org/foo.pdf" />',
     1537                '<object type="application/pdf" data="https://example.org/foo.pdf" />',
    15381538            ),
    15391539            'multiple type attributes, first invalid' => array(
    1540                 '<object type="application/exe" type="application/pdf" data="https://wordpress.org/foo.pdf" />',
     1540                '<object type="application/exe" type="application/pdf" data="https://example.org/foo.pdf" />',
    15411541                '',
    15421542            ),
    15431543            'multiple type attributes, first upper case and invalid' => array(
    1544                 '<object TYPE="application/exe" type="application/pdf" data="https://wordpress.org/foo.pdf" />',
     1544                '<object TYPE="application/exe" type="application/pdf" data="https://example.org/foo.pdf" />',
    15451545                '',
    15461546            ),
    15471547            'multiple type attributes, first invalid, last uppercase' => array(
    1548                 '<object type="application/exe" TYPE="application/pdf" data="https://wordpress.org/foo.pdf" />',
     1548                '<object type="application/exe" TYPE="application/pdf" data="https://example.org/foo.pdf" />',
    15491549                '',
    15501550            ),
    15511551            'multiple object tags, last invalid'      => array(
    1552                 '<object type="application/pdf" data="https://wordpress.org/foo.pdf" /><object type="application/exe" data="https://wordpress.org/foo.exe" />',
    1553                 '<object type="application/pdf" data="https://wordpress.org/foo.pdf" />',
     1552                '<object type="application/pdf" data="https://example.org/foo.pdf" /><object type="application/exe" data="https://example.org/foo.exe" />',
     1553                '<object type="application/pdf" data="https://example.org/foo.pdf" />',
    15541554            ),
    15551555            'multiple object tags, first invalid'     => array(
    1556                 '<object type="application/exe" data="https://wordpress.org/foo.exe" /><object type="application/pdf" data="https://wordpress.org/foo.pdf" />',
    1557                 '<object type="application/pdf" data="https://wordpress.org/foo.pdf" />',
     1556                '<object type="application/exe" data="https://example.org/foo.exe" /><object type="application/pdf" data="https://example.org/foo.pdf" />',
     1557                '<object type="application/pdf" data="https://example.org/foo.pdf" />',
    15581558            ),
    15591559            'type attribute with partially incorrect value' => array(
    1560                 '<object type="application/pdfa" data="https://wordpress.org/foo.pdf" />',
     1560                '<object type="application/pdfa" data="https://example.org/foo.pdf" />',
    15611561                '',
    15621562            ),
    15631563            'type attribute with empty value'         => array(
    1564                 '<object type="" data="https://wordpress.org/foo.pdf" />',
     1564                '<object type="" data="https://example.org/foo.pdf" />',
    15651565                '',
    15661566            ),
    15671567            'type attribute with no value'            => array(
    1568                 '<object type data="https://wordpress.org/foo.pdf" />',
     1568                '<object type data="https://example.org/foo.pdf" />',
    15691569                '',
    15701570            ),
    15711571            'no type attribute'                       => array(
    1572                 '<object data="https://wordpress.org/foo.pdf" />',
     1572                '<object data="https://example.org/foo.pdf" />',
     1573                '',
     1574            ),
     1575            'different protocol in url'               => array(
     1576                '<object type="application/pdf" data="http://example.org/foo.pdf" />',
     1577                '<object type="application/pdf" data="http://example.org/foo.pdf" />',
     1578            ),
     1579            'query string on url'                     => array(
     1580                '<object type="application/pdf" data="https://example.org/foo.pdf?lol=.pdf" />',
     1581                '',
     1582            ),
     1583            'fragment on url'                         => array(
     1584                '<object type="application/pdf" data="https://example.org/foo.pdf#lol.pdf" />',
     1585                '',
     1586            ),
     1587            'wrong extension'                         => array(
     1588                '<object type="application/pdf" data="https://example.org/foo.php" />',
     1589                '',
     1590            ),
     1591            'protocol relative url'                   => array(
     1592                '<object type="application/pdf" data="//example.org/foo.pdf" />',
     1593                '',
     1594            ),
     1595            'relative url'                            => array(
     1596                '<object type="application/pdf" data="/cat/foo.pdf" />',
    15731597                '',
    15741598            ),
Note: See TracChangeset for help on using the changeset viewer.