Improve filtering of "allow" and "referrerpolicy" attributes of <iframe>

This commit is contained in:
Kijin Sung 2023-08-16 22:41:14 +09:00
parent 2f97adb9bb
commit ea345ad7e1
2 changed files with 38 additions and 1 deletions

View file

@ -23,6 +23,21 @@ class HTMLFilter
protected static $_preproc = array();
protected static $_postproc = array();
/**
* Default permissions for iframes.
*/
protected static $_iframe_permissions = array(
'accelerometer' => true,
'autoplay' => true,
'clipboard-write' => true,
'encrypted-media' => true,
'fullscreen' => true,
'gyroscope' => true,
'picture-in-picture' => true,
'screen-wake-lock' => true,
'web-share' => true,
);
/**
* Prepend a pre-processing filter.
*
@ -301,8 +316,9 @@ class HTMLFilter
$def->addAttribute('i', 'aria-hidden', 'Text');
$def->addAttribute('img', 'srcset', 'Text');
$def->addAttribute('img', 'data-file-srl', 'Number');
$def->addAttribute('iframe', 'allowfullscreen', 'Bool');
$def->addAttribute('iframe', 'allow', 'Text');
$def->addAttribute('iframe', 'allowfullscreen', 'Bool');
$def->addAttribute('iframe', 'referrerpolicy', 'Enum#no-referrer,no-referrer-when-downgrade,origin,origin-when-cross-origin,same-origin,strict-origin,strict-origin-when-cross-origin,unsafe-url');
// Support contenteditable="false" (#1710)
$def->addAttribute('div', 'contenteditable', 'Enum#false');
@ -497,6 +513,19 @@ class HTMLFilter
return htmlspecialchars($matches[0], ENT_QUOTES, 'UTF-8');
}, $content);
// Remove "allow" attributes that should not be allowed.
$content = preg_replace_callback('!(?<=\s)allow="([^"<>]*?)"!i', function($matches) {
$result = [];
foreach (array_map('trim', explode(';', $matches[1])) as $value)
{
if (isset(self::$_iframe_permissions[$value]))
{
$result[] = $value;
}
}
return 'allow="' . implode('; ', $result) . '"';
}, $content);
// Remove object and embed URLs that are not allowed.
$whitelist = MediaFilter::getWhitelistRegex();
$content = preg_replace_callback('!<(object|embed|param|audio|video|source|track)([^>]+)>!i', function($matches) use($whitelist) {

View file

@ -118,6 +118,14 @@ class HTMLFilterTest extends \Codeception\TestCase\Test
$target = '<iframe title="Video Test" width="640" height="360" frameborder="0" scrolling="no"></iframe>';
$this->assertEquals($target, Rhymix\Framework\Filters\HTMLFilter::clean($source));
$source = '<iframe src="https://www.youtube.com/" allow="autoplay; nonexistent; disallowd-feature; encrypted-media; picture-in-picture" allowfullscreen></iframe>';
$target = '<iframe src="https://www.youtube.com/" allow="autoplay; encrypted-media; picture-in-picture" allowfullscreen=""></iframe>';
$this->assertEquals($target, Rhymix\Framework\Filters\HTMLFilter::clean($source));
$source = '<iframe src="https://www.youtube.com/" referrerpolicy="no-referrer" hello="world"></iframe>';
$target = '<iframe src="https://www.youtube.com/" referrerpolicy="no-referrer"></iframe>';
$this->assertEquals($target, Rhymix\Framework\Filters\HTMLFilter::clean($source));
$source = '<object type="application/x-shockwave-flash" width="640px" height="360px" align="middle" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,3,0,0">' .
'<param name="movie" value="http://videofarm.daum.net/controller/player/VodPlayer.swf" />' .
'<param name="allowScriptAccess" value="always" />' .