Skip to content

[HtmlSanitizer] Access to undefined key in UrlSanitizer #59524

Closed
@Stoakes

Description

@Stoakes

Symfony version(s) affected

6.1.0 and above

Description

Hello,

I'm getting an error when sanitizing a text with urls. I have multiple allowed hosts in my config, and thus html sanitization for urls fails with access to undefined keys when calling UrlSanitizer->matchAllowedHostParts.

Here are details about narrowing down the issue to `UrlSanitizer->matchAllowedHostParts` This becomes quite obvious that when looking at `matchAllowedHostParts`
# src/Symfony/Component/HtmlSanitizer/TextSanitizer/UrlSanitizer.php
private static function matchAllowedHostParts(array $uriParts, array $trustedParts): bool
    {
        // Check each chunk of the domain is valid
        foreach ($trustedParts as $key => $trustedPart) {
            if ($uriParts[$key] !== $trustedPart) {
                return false;
            }
        }

        return true;
    }

when $trustedParts is longer than $uriParts. It eventually ends with a warning : Warning: Undefined array key 2.

How to reproduce

Here is a way to reproduce the issue through HtmlSanitizer unit tests :

  1. Open src/Symfony/Component/HtmlSanitizer/Tests/TextSanitizer/UrlSanitizerTest.php
  2. Add the following test case :
         yield [
             'input' => 'https://trusted.com/link.php',
             'allowedSchemes' => ['http', 'https'],
             'allowedHosts' => ['subdomain.trusted.com', 'trusted.com'],
             'forceHttps' => false,
             'allowRelative' => false,
             'expected' => 'https://trusted.com/link.php',
         ];
3. Test fails with : 

  1. Symfony\Component\HtmlSanitizer\Tests\TextSanitizer\UrlSanitizerTest::testSanitize with data set Switched to submodules #27 ('https://trusted.com/link.php', array('http', 'https'), array('subdomain.trusted.com', 'trusted.com'), false, false, 'https://trusted.com/link.php')
    Undefined array key 2

/home/stoakes/dev/symfony/src/Symfony/Component/HtmlSanitizer/TextSanitizer/UrlSanitizer.php:135
/home/stoakes/dev/symfony/src/Symfony/Component/HtmlSanitizer/TextSanitizer/UrlSanitizer.php:123
/home/stoakes/dev/symfony/src/Symfony/Component/HtmlSanitizer/TextSanitizer/UrlSanitizer.php:63
/home/stoakes/dev/symfony/src/Symfony/Component/HtmlSanitizer/Tests/TextSanitizer/UrlSanitizerTest.php:24


### Possible Solution

I would check that key exists before accessing it. Roughly : 

```php
private static function matchAllowedHostParts(array $uriParts, array $trustedParts): bool
    {
        // Check each chunk of the domain is valid
        foreach ($trustedParts as $key => $trustedPart) {
            if (array_key_exists($key, $uriParts) && $uriParts[$key] !== $trustedPart) {
                return false;
            }
        }

        return true;
    }

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions