Content filtering: Added srcset protocol filter

Upstream libraries used did not specifically treat values in srcset as
URIs like other attributes, so this adds a simple filter for possible
bad values.
Updated tests to cover.

Thanks for Gurmandeep Deol for reporting.
This commit is contained in:
Dan Brown
2026-06-30 18:35:34 +01:00
parent f7df78b91b
commit 59bbf504cf
4 changed files with 33 additions and 2 deletions

View File

@@ -156,6 +156,10 @@ class ConfiguredHtmlPurifier
// Allow mention-ids on links
$definition->addAttribute('a', 'data-mention-user-id', 'Number');
// Set up custom handler for srcset to limit accepted types
$definition->addAttribute('img', 'srcset', new SrcsetAttrDef());
$definition->addAttribute('source', 'srcset', new SrcsetAttrDef());
}
protected function configureUriDefinition(HTMLPurifier_URIDefinition $definition): void

View File

@@ -51,5 +51,3 @@ class UriLimitFileProtocolToAnchors extends HTMLPurifier_URIFilter
return false;
}
}
// vim: et sw=4 sts=4

View File

@@ -0,0 +1,26 @@
<?php
namespace BookStack\Util\HtmlPurifier;
use HTMLPurifier_AttrDef;
/**
* Custom attribute definition to filter out potentially dangerous
* values from the srcset attribute.
*/
class SrcsetAttrDef extends HTMLPurifier_AttrDef
{
public function validate($string, $config, $context)
{
$lower = strtolower($string);
$nonAllowed = ['javascript:', 'vbscript:', 'data:', 'file:'];
foreach ($nonAllowed as $nonAllowedString) {
if (str_contains($lower, $nonAllowedString)) {
return false;
}
}
return $string;
}
}

View File

@@ -469,6 +469,9 @@ HTML;
'<object data="file://link/to/file" id="bkmrk-file-object"></object>' => '<object id="bkmrk-file-object">',
'<div id="bkmrk-file-img"><img src="file://link/to/file" alt="My local image"></div>' => '<div id="bkmrk-file-img"></div>',
'<div id="bkmrk-file-img"><img srcset="file://link/to/file" alt="My local image"></div>' => '<div id="bkmrk-file-img"></div>',
'<div id="bkmrk-file-img"><img src="http://example.com" srcset="file://link/to/file 2x" alt="My local image"></div>' => '<div id="bkmrk-file-img"><img src="http://example.com" alt="My local image"></div>',
'<div id="bkmrk-file-img"><picture><source srcset="file://link/to/file"/><img src="http://example.com" alt="cat"/></picture></div>' => '<div id="bkmrk-file-img"><picture><source><img src="http://example.com" alt="cat"></picture></div>',
'<div id="bkmrk-link"><link rel="preload" as="image" imagesizes="50vw" imagesrcset="file://cat.com, bg-wide.png 800w" /></div>' => '<div id="bkmrk-link"></div>',
];
config()->set('app.content_filtering', 'a');