Ticket #45067: 45067.5.diff
File 45067.5.diff, 6.7 KB (added by , 6 years ago) |
---|
-
src/wp-includes/kses.php
diff --git src/wp-includes/kses.php src/wp-includes/kses.php index 0cf4ce14c4..5e474fa5aa 100644
function kses_init() { 1687 1687 * @return string Filtered string of CSS rules. 1688 1688 */ 1689 1689 function safecss_filter_attr( $css, $deprecated = '' ) { 1690 if ( ! empty( $deprecated ) )1690 if ( ! empty( $deprecated ) ) 1691 1691 _deprecated_argument( __FUNCTION__, '2.8.1' ); // Never implemented 1692 1692 1693 $css = wp_kses_no_null($css); 1694 $css = str_replace(array("\n","\r","\t"), '', $css); 1695 1696 if ( preg_match( '%[\\\\(&=}]|/\*%', $css ) ) // remove any inline css containing \ ( & } = or comments 1697 return ''; 1693 $css = wp_kses_no_null( $css ); 1694 $css = str_replace( array( "\n", "\r", "\t" ), '', $css ); 1695 $allowed_protocols = wp_allowed_protocols(); 1698 1696 1699 1697 $css_array = explode( ';', trim( $css ) ); 1700 1698 … … function safecss_filter_attr( $css, $deprecated = '' ) { 1710 1708 $allowed_attr = apply_filters( 'safe_style_css', array( 1711 1709 'background', 1712 1710 'background-color', 1711 'background-image', 1713 1712 1714 1713 'border', 1715 1714 'border-width', … … function safecss_filter_attr( $css, $deprecated = '' ) { 1778 1777 'list-style-type', 1779 1778 ) ); 1780 1779 1781 if ( empty($allowed_attr) ) 1780 1781 /* 1782 * CSS attributes that accept URL data types. 1783 * 1784 * This is in accordance to the CSS spec and unrelated to 1785 * the sub-set of supported attributes above. 1786 * 1787 * See: https://developer.mozilla.org/en-US/docs/Web/CSS/url 1788 */ 1789 $css_url_data_types = array( 1790 'background', 1791 'background-image', 1792 1793 'cursor', 1794 1795 'list-style', 1796 'list-style-image', 1797 ); 1798 1799 if ( empty( $allowed_attr ) ) { 1782 1800 return $css; 1801 } 1783 1802 1784 1803 $css = ''; 1785 1804 foreach ( $css_array as $css_item ) { 1786 if ( $css_item == '' ) 1805 if ( $css_item == '' ) { 1787 1806 continue; 1788 $css_item = trim( $css_item ); 1789 $found = false; 1807 } 1808 1809 $css_item = trim( $css_item ); 1810 $css_test_string = $css_item; 1811 $found = false; 1812 $url_attr = false; 1813 1790 1814 if ( strpos( $css_item, ':' ) === false ) { 1791 1815 $found = true; 1792 1816 } else { 1793 $parts = explode( ':', $css_item ); 1794 if ( in_array( trim( $parts[0] ), $allowed_attr ) ) 1817 $parts = explode( ':', $css_item, 2 ); 1818 $css_selector = trim( $parts[0] ); 1819 1820 if ( in_array( $css_selector, $allowed_attr, true ) ) { 1795 1821 $found = true; 1822 $url_attr = in_array( $css_selector, $css_url_data_types, true ); 1823 } 1824 } 1825 1826 if ( $found && $url_attr ) { 1827 // Simplified: matches the sequence `url(*)`. 1828 preg_match_all( '/url\([^)]+\)/', $parts[1], $url_matches ); 1829 1830 foreach ( $url_matches[0] as $url_match ) { 1831 // Clean up the URL from each of the matches above. 1832 preg_match( '/^url\(\s*([\'\"]?)(.*)(\g1)\s*\)$/', $url_match, $url_pieces ); 1833 $url = trim( $url_pieces[2] ); 1834 1835 if ( empty( $url ) || $url !== wp_kses_bad_protocol( $url, $allowed_protocols ) ) { 1836 $found = false; 1837 break; 1838 } else { 1839 // Remove the whole `url(*)` bit that was matched above from the CSS. 1840 $css_test_string = str_replace( $url_match, '', $css_test_string ); 1841 } 1842 } 1796 1843 } 1797 if ( $found ) { 1798 if( $css != '' ) 1844 1845 if ( $found && ! preg_match( '%[\\\(&=}]|/\*%', $css_test_string ) ) { 1846 if ( $css != '' ) { 1799 1847 $css .= ';'; 1848 } 1849 1800 1850 $css .= $css_item; 1801 1851 } 1802 1852 } -
tests/phpunit/tests/kses.php
diff --git tests/phpunit/tests/kses.php tests/phpunit/tests/kses.php index dea4a881a2..ccb1502f22 100644
EOF; 718 718 719 719 $this->assertEquals( "<{$element}>", wp_kses_attr( $element, $attribute, array( 'foo' => false ), array() ) ); 720 720 } 721 722 /** 723 * Test URL sanitization in the style tag. 724 * 725 * @dataProvider data_kses_style_attr_with_url 726 * 727 * @ticket 45067 728 * 729 * @param $input string The style attribute saved in the editor. 730 * @param $expected string The sanitized style attribute. 731 */ 732 function test_kses_style_attr_with_url( $input, $expected ) { 733 $actual = safecss_filter_attr( $input ); 734 735 $this->assertSame( $expected, $actual ); 736 } 737 738 /** 739 * Data provider testing style attribute sanitization. 740 * 741 * @return array Nested array of input, expected pairs. 742 */ 743 function data_kses_style_attr_with_url() { 744 return array( 745 /* 746 * Valid use cases. 747 */ 748 749 // Double quotes. 750 array( 751 'background-image: url( "http://example.com/valid.gif" );', 752 'background-image: url( "http://example.com/valid.gif" )', 753 ), 754 755 // Single quotes. 756 array( 757 "background-image: url( 'http://example.com/valid.gif' );", 758 "background-image: url( 'http://example.com/valid.gif' )", 759 ), 760 761 // No quotes. 762 array( 763 'background-image: url( http://example.com/valid.gif );', 764 'background-image: url( http://example.com/valid.gif )', 765 ), 766 767 // Single quotes, extra spaces. 768 array( 769 "background-image: url( ' http://example.com/valid.gif ' );", 770 "background-image: url( ' http://example.com/valid.gif ' )", 771 ), 772 773 // Line breaks, single quotes. 774 array( 775 "background-image: url(\n'http://example.com/valid.gif' );", 776 "background-image: url('http://example.com/valid.gif' )", 777 ), 778 779 // Tabs not spaces, single quotes. 780 array( 781 "background-image: url(\t'http://example.com/valid.gif'\t\t);", 782 "background-image: url('http://example.com/valid.gif')", 783 ), 784 785 // Single quotes, absolute path. 786 array( 787 "background: url('/valid.gif');", 788 "background: url('/valid.gif')", 789 ), 790 791 // Single quotes, relative path. 792 array( 793 "background: url('../wp-content/uploads/2018/10/valid.gif');", 794 "background: url('../wp-content/uploads/2018/10/valid.gif')", 795 ), 796 797 // Error check: valid property not containing a URL. 798 array( 799 "background: red", 800 "background: red", 801 ), 802 803 /* 804 * Invalid use cases. 805 */ 806 807 // Attribute doesn't support URL properties. 808 array( 809 'color: url( "http://example.com/invalid.gif" );', 810 '', 811 ), 812 813 // Mismatched quotes. 814 array( 815 'background-image: url( "http://example.com/valid.gif\' );', 816 '', 817 ), 818 819 // Bad protocol, double quotes. 820 array( 821 'background-image: url( "bad://example.com/invalid.gif" );', 822 '', 823 ), 824 825 // Bad protocol, single quotes. 826 array( 827 "background-image: url( 'bad://example.com/invalid.gif' );", 828 '', 829 ), 830 831 // Bad protocol, single quotes. 832 array( 833 "background-image: url( 'bad://example.com/invalid.gif' );", 834 '', 835 ), 836 837 // Bad protocol, single quotes, strange spacing. 838 array( 839 "background-image: url( ' \tbad://example.com/invalid.gif ' );", 840 '', 841 ), 842 843 // Bad protocol, no quotes. 844 array( 845 'background-image: url( bad://example.com/invalid.gif );', 846 '', 847 ), 848 849 // No URL inside url(). 850 array( 851 'background-image: url();', 852 '', 853 ), 854 ); 855 } 721 856 }