Affected versions

Symfony versions >=6.1, <6.4.40, >=7, <7.4.12, >=8, <8.0.12 of the Symfony HTML Sanitizer component are affected by this security issue.

The issue has been fixed in Symfony 6.4.40, 7.4.12, 8.0.12.

Description

Symfony\Component\HtmlSanitizer\TextSanitizer\UrlSanitizer::parse() (used by UrlSanitizer::sanitize() and therefore by every HtmlSanitizer config that allows links or media) accepts URLs that contain Unicode explicit-direction BiDi formatting characters: U+202A-U+202E (LRE / RLE / PDF / LRO / RLO) and U+2066-U+2069 (LRI / RLI / FSI / PDI). These characters are passed through unchanged into the href / src attributes produced by HtmlSanitizer. When the resulting HTML is rendered in a browser, the override characters reverse or alter the visual ordering of the URL text, so the displayed link can differ arbitrarily from the actual destination: a classic visual-spoofing / phishing primitive against viewers of sanitized content.

Resolution

UrlSanitizer::parse() now rejects URLs containing the explicit-direction BiDi formatting code points (U+202A-U+202E, U+2066-U+2069) before invoking the underlying URL parser. As an unrelated companion fix in the same patch, spaces inside path/query/fragment are now percent-encoded rather than rejected outright, while spaces in the scheme/authority remain rejected by the post-encoding whitespace check.

The patch for this issue is available here for branch 5.4.

Credits

We would like to thank Nicolas Grekas for reporting the issue and providing the fix.