Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2bf9709
attempt to bring 29807.8.diff up to date with trunk
adamsilverstein Feb 26, 2024
11336a3
Merge remote-tracking branch 'upstream/trunk' into pr/6184
azaozz Mar 11, 2024
05dcd69
Fix coding standards spaces and methods visibility
azaozz Mar 11, 2024
499dc82
More CS empty space fixes.
azaozz Mar 11, 2024
7a75eba
Merge branch 'trunk' into ticket/29807
adamsilverstein Aug 15, 2025
69312e7
Apply suggestion from @azaozz
adamsilverstein Aug 15, 2025
3c6defd
string in_array test
adamsilverstein Aug 15, 2025
c88673d
expand test slightly
adamsilverstein Aug 15, 2025
022def5
Cleanup; move multi_uri to parameter
adamsilverstein Aug 15, 2025
321e441
phpcbf
adamsilverstein Aug 15, 2025
c7c63dd
add sizes attribute to test
adamsilverstein Aug 15, 2025
e3c1684
enable sizes
adamsilverstein Aug 15, 2025
3862627
Improve doc block
adamsilverstein Aug 15, 2025
4cb049a
test clean up
adamsilverstein Aug 15, 2025
ca94908
Update tests/phpunit/tests/kses.php
adamsilverstein Aug 17, 2025
49f1ba6
Update src/wp-includes/kses.php
adamsilverstein Aug 17, 2025
2b5706c
remove unused $uris
adamsilverstein Aug 17, 2025
d116c8e
Add additional test cases.
adamsilverstein Aug 17, 2025
fbeed82
Merge branch 'trunk' into ticket/29807
adamsilverstein Aug 27, 2025
f9e002c
phpcbf
adamsilverstein Aug 27, 2025
80521e4
Merge remote-tracking branch 'origin/trunk' into ticket/29807
adamsilverstein Mar 13, 2026
0068aac
Add tests exposing srcset and img attribute bugs
adamsilverstein Mar 13, 2026
f11aeb2
Add decoding and fetchpriority to img allowed attrs
adamsilverstein Mar 13, 2026
cdb84fc
Fix srcset URI sanitization for URLs with commas
adamsilverstein Mar 13, 2026
399aa30
Fix array double arrow alignment in kses tests
adamsilverstein Mar 13, 2026
e5488a6
Merge branch 'trunk' into ticket/29807
adamsilverstein Mar 14, 2026
1f02276
Add kses srcset/picture tests, update @since tag
adamsilverstein Mar 14, 2026
9bb1ebf
Fix array double arrow alignment in new tests
adamsilverstein Mar 14, 2026
2bdc1f9
Merge branch 'trunk' into ticket/29807
adamsilverstein Mar 14, 2026
61881bf
Merge branch 'trunk' into ticket/29807
adamsilverstein Apr 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 51 additions & 14 deletions src/wp-includes/kses.php
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@
'longdesc' => true,
'vspace' => true,
'src' => true,
'srcset' => true,
Comment thread
adamsilverstein marked this conversation as resolved.
Outdated
'usemap' => true,
'width' => true,
),
Expand Down Expand Up @@ -250,6 +251,7 @@
'p' => array(
'align' => true,
),
'picture' => array(),
'pre' => array(
'width' => true,
),
Expand All @@ -270,6 +272,12 @@
'align' => true,
),
'small' => array(),
'source' => array(
'srcset' => true,
'type' => true,
'media' => true,
'sizes' => true,
),
'strike' => array(),
'strong' => array(),
'sub' => array(),
Expand Down Expand Up @@ -768,7 +776,6 @@ function wp_kses( $content, $allowed_html, $allowed_protocols = array() ) {
* @return string Filtered attribute.
*/
function wp_kses_one_attr( $attr, $element ) {
Comment thread
adamsilverstein marked this conversation as resolved.
$uris = wp_kses_uri_attributes();
$allowed_html = wp_kses_allowed_html( 'post' );
$allowed_protocols = wp_allowed_protocols();
$attr = wp_kses_no_null( $attr, array( 'slash_zero' => 'keep' ) );
Expand Down Expand Up @@ -812,10 +819,7 @@ function wp_kses_one_attr( $attr, $element ) {
// Sanitize quotes, angle braces, and entities.
$value = esc_attr( $value );

// Sanitize URI values.
if ( in_array( strtolower( $name ), $uris, true ) ) {
$value = wp_kses_bad_protocol( $value, $allowed_protocols );
}
$value = wp_kses_sanitize_uris( $name, $value, $allowed_protocols );

$attr = "$name=$quote$value$quote";
$vless = 'n';
Expand Down Expand Up @@ -1380,9 +1384,9 @@ function wp_kses_hair( $attr, $allowed_protocols ) {
if ( preg_match( '%^"([^"]*)"(\s+|/?$)%', $attr, $match ) ) {
// "value"
$thisval = $match[1];
if ( in_array( strtolower( $attrname ), $uris, true ) ) {
$thisval = wp_kses_bad_protocol( $thisval, $allowed_protocols );
}

// Sanitize URI values.
$thisval = wp_kses_sanitize_uris( $attrname, $thisval, $allowed_protocols );

if ( false === array_key_exists( $attrname, $attrarr ) ) {
$attrarr[ $attrname ] = array(
Expand All @@ -1402,9 +1406,8 @@ function wp_kses_hair( $attr, $allowed_protocols ) {
if ( preg_match( "%^'([^']*)'(\s+|/?$)%", $attr, $match ) ) {
// 'value'
$thisval = $match[1];
if ( in_array( strtolower( $attrname ), $uris, true ) ) {
$thisval = wp_kses_bad_protocol( $thisval, $allowed_protocols );
}
// Sanitize URI values.
$thisval = wp_kses_sanitize_uris( $attrname, $thisval, $allowed_protocols );

if ( false === array_key_exists( $attrname, $attrarr ) ) {
$attrarr[ $attrname ] = array(
Expand All @@ -1424,9 +1427,8 @@ function wp_kses_hair( $attr, $allowed_protocols ) {
if ( preg_match( "%^([^\s\"']+)(\s+|/?$)%", $attr, $match ) ) {
// value
$thisval = $match[1];
if ( in_array( strtolower( $attrname ), $uris, true ) ) {
$thisval = wp_kses_bad_protocol( $thisval, $allowed_protocols );
}
// Sanitize URI values.
$thisval = wp_kses_sanitize_uris( $attrname, $thisval, $allowed_protocols );

if ( false === array_key_exists( $attrname, $attrarr ) ) {
$attrarr[ $attrname ] = array(
Expand Down Expand Up @@ -1468,6 +1470,41 @@ function wp_kses_hair( $attr, $allowed_protocols ) {
return $attrarr;
}

/**
* Santizes uris in attributes
*
* This condenses code that was spread around two functions and several cases. It places the list of attributes
* which can have uris in them and checks for ones that can have multiple uri candidates (like srcset)
* It ultimately passes everything to wp_kses_bad_protocol() to do the actual work.
*
* @since ?
*
* @param string $attrname Attribute name to test against.
* @param string $attrvalue Content to filter bad protocols from.
* @param string[] $allowed_protocols Array of allowed URL protocols.
* @return string Filtered content.
*/
function wp_kses_sanitize_uris( $attrname, $attrvalue, $allowed_protocols ) {
$uris = wp_kses_uri_attributes();
$uri_candidates = array( 'srcset' );
Comment thread
adamsilverstein marked this conversation as resolved.
Outdated

if ( ! in_array( strtolower( $attrname ), $uris ) ) {
return $attrvalue;
} else {
if ( in_array( strtolower( $attrname ), $uri_candidates ) ) {
$thesevals = preg_split( '/\s*,\s+/', $attrvalue );
Comment thread
adamsilverstein marked this conversation as resolved.
Outdated
} else {
$thesevals = array( $attrvalue );
}
Comment thread
adamsilverstein marked this conversation as resolved.
Outdated
Comment thread
adamsilverstein marked this conversation as resolved.
Outdated
}

foreach ( (array) $thesevals as $key => $val ) {
$thesevals[$key] = wp_kses_bad_protocol( $val, $allowed_protocols );
}

return join(', ', $thesevals);
}

/**
* Finds all attributes of an HTML element.
*
Expand Down
94 changes: 94 additions & 0 deletions tests/phpunit/tests/kses.php
Original file line number Diff line number Diff line change
Expand Up @@ -2188,4 +2188,98 @@ public function data_kses_globals_are_defined() {

return $this->text_array_to_dataprovider( $required_kses_globals );
}

/**
* @ticket 29807
*/
function test_wp_filter_post_kses_img() {
global $allowedposttags;

$attributes = array(
'class' => 'classname',
'id' => 'idattr',
'style' => 'color: red;',
'alt' => 'alt',
'src' => '/test.png',
'srcset' => '/test.png 1x, /test-2x.png 2x',
Comment thread
adamsilverstein marked this conversation as resolved.
Outdated
'width' => '100',
'height' => '100',
'usemap' => '#hash',
'vspace' => '20',
'hspace' => '20',
'longdesc' => 'this is the longdesc',
'align' => 'middle',
'border' => '5',
);

foreach ( $attributes as $name => $value ) {
if ( $name === $value ) {
$string = "<img $value />";
$expect_string = '<img ' . trim( $value, ';' ) . ' />';
} else {
$string = "<img $name='$value' />";
$expect_string = "<img $name='" . trim( $value, ';' ) . "' />";
}

$this->assertEquals( $expect_string, wp_kses( $string, $allowedposttags ) );
}
}

/**
* @ticket 29807
*
* @param string $unfiltered Unfiltered srcset value before wp_kses.
* @param string $expected Expected srset value after wp_kses.
Comment thread
adamsilverstein marked this conversation as resolved.
Outdated
*
* @dataProvider data_wp_kses_srcset
*/
function test_wp_kses_srcset( $unfiltered, $expected ) {
$unfiltered = "<img src='test.png' srcset='{$unfiltered}' />";
$expected = "<img src='test.png' srcset='{$expected}' />";
$this->assertEquals( $expected, wp_kses_post( $unfiltered ) );
}

function data_wp_kses_srcset() {
return array(
array(
'/test.png 1x, /test-2x.png 2x',
'/test.png 1x, /test-2x.png 2x',
),
array(
'bad://localhost/test.png 1x, http://localhost/test-2x.png 2x',
'//localhost/test.png 1x, http://localhost/test-2x.png 2x',
),
array(
'http://localhost/test.png 1x, bad://localhost/test-2x.png 2x',
'http://localhost/test.png 1x, //localhost/test-2x.png 2x',
),
array(
'http://localhost/test.png,big 1x, bad://localhost/test.png,medium 2x',
'http://localhost/test.png,big 1x, //localhost/test.png,medium 2x',
),
array(
'path/to/test.png 1x, path/to/test-2x.png 2x',
'path/to/test.png 1x, path/to/test-2x.png 2x',
),
);
}

/**
* @ticket 29807
*/
function test_wp_filter_post_kses_picture() {
global $allowedposttags;

$html = '<picture><source srcset="pear-mobile.jpeg" media="(max-width: 720px)" type="image/png"><source srcset="pear-tablet.jpeg" media="(max-width: 1280px)" type="image/png"><img src="pear-desktop.jpeg" alt="The pear is juicy."></picture>';
$this->assertEquals( $html, wp_kses( $html, $allowedposttags ) );

$html = '<picture><source srcset="https://wordpress.org/pear-mobile.jpeg" media="(max-width: 720px)" type="image/png"><source srcset="https://wordpress.org/pear-tablet.jpeg 500w, https://wordpress.org/pear-tablet.jpeg" media="(max-width: 1280px)" type="image/png"><img src="pear-desktop.jpeg" alt="The pear is juicy."></picture>';
$this->assertEquals( $html, wp_kses( $html, $allowedposttags ) );

// Test bad protocol in srcset
$original = '<picture><source srcset="bad://pear-mobile.jpeg" media="(max-width: 720px)" type="image/png"><source srcset="pear-tablet.jpeg" media="(max-width: 1280px)" type="image/png"><img src="pear-desktop.jpeg" alt="The pear is juicy."></picture>';
$expected = '<picture><source srcset="//pear-mobile.jpeg" media="(max-width: 720px)" type="image/png"><source srcset="pear-tablet.jpeg" media="(max-width: 1280px)" type="image/png"><img src="pear-desktop.jpeg" alt="The pear is juicy."></picture>';
$this->assertEquals( $expected, wp_kses( $original, $allowedposttags ) );
}

}