diff --git a/src/Util/RegexHelper.php b/src/Util/RegexHelper.php index 429b2d85f..3d9a2912e 100644 --- a/src/Util/RegexHelper.php +++ b/src/Util/RegexHelper.php @@ -66,7 +66,7 @@ final class RegexHelper '|' . '\((' . self::PARTIAL_ESCAPED_CHAR . '|[^()\x00])*+\))'; public const REGEX_PUNCTUATION = '/^[\p{P}\p{S}]/u'; - public const REGEX_UNSAFE_PROTOCOL = '/^javascript:|vbscript:|file:|data:/i'; + public const REGEX_UNSAFE_PROTOCOL = '/^(?:javascript|vbscript|file|data):/i'; public const REGEX_SAFE_DATA_PROTOCOL = '/^data:image\/(?:png|gif|jpeg|webp)/i'; public const REGEX_NON_SPACE = '/[^ \t\f\v\r\n]/'; diff --git a/tests/unit/Util/RegexHelperTest.php b/tests/unit/Util/RegexHelperTest.php index 143449aa2..7b91bba2f 100644 --- a/tests/unit/Util/RegexHelperTest.php +++ b/tests/unit/Util/RegexHelperTest.php @@ -402,6 +402,38 @@ public static function blockTypesWithInvalidCloserRegexes(): iterable yield [8]; } + /** + * @dataProvider dataForTestIsLinkPotentiallyUnsafe + */ + #[DataProvider('dataForTestIsLinkPotentiallyUnsafe')] + public function testIsLinkPotentiallyUnsafe(string $url, bool $expected): void + { + $this->assertSame($expected, RegexHelper::isLinkPotentiallyUnsafe($url)); + } + + /** + * @return iterable> + */ + public static function dataForTestIsLinkPotentiallyUnsafe(): iterable + { + return [ + // Dangerous leading schemes are unsafe + ['javascript:alert(1)', true], + ['JAVASCRIPT:alert(1)', true], + ['vbscript:msgbox(1)', true], + ['file:///etc/passwd', true], + ['data:text/html,', true], + ['data:image/svg+xml,', true], + // Safe data: images are allowed + ['data:image/png;base64,iVBORw0KGgo=', false], + // URLs merely containing those schemes elsewhere are safe + ['https://example.com/view?src=data:image/png', false], + ['https://example.com/download?to=file:report', false], + ['https://example.com/wiki/vbscript:_basics', false], + ['https://example.com/ok', false], + ]; + } + private function assertRegexMatches(string $pattern, string $string, string $message = ''): void { if (\method_exists($this, 'assertMatchesRegularExpression')) {