diff --git a/application/Espo/Tools/UserSecurity/Password/Recovery/UrlValidator.php b/application/Espo/Tools/UserSecurity/Password/Recovery/UrlValidator.php index b0a93eb467..6451dd8369 100644 --- a/application/Espo/Tools/UserSecurity/Password/Recovery/UrlValidator.php +++ b/application/Espo/Tools/UserSecurity/Password/Recovery/UrlValidator.php @@ -48,7 +48,7 @@ class UrlValidator { $siteUrl = rtrim($this->config->get('siteUrl') ?? '', '/'); - if (str_starts_with($url, $siteUrl)) { + if (UrlValidatorUtil::validate($url, $siteUrl)) { return; } @@ -60,7 +60,7 @@ class UrlValidator foreach ($portals as $portal) { $siteUrl = rtrim($portal->getUrl() ?? '', '/'); - if (str_starts_with($url, $siteUrl)) { + if (UrlValidatorUtil::validate($url, $siteUrl)) { return; } } diff --git a/application/Espo/Tools/UserSecurity/Password/Recovery/UrlValidatorUtil.php b/application/Espo/Tools/UserSecurity/Password/Recovery/UrlValidatorUtil.php new file mode 100644 index 0000000000..3428ca2cbf --- /dev/null +++ b/application/Espo/Tools/UserSecurity/Password/Recovery/UrlValidatorUtil.php @@ -0,0 +1,59 @@ +. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. + ************************************************************************/ + +namespace Espo\Tools\UserSecurity\Password\Recovery; + +use const FILTER_VALIDATE_URL; +use const PHP_URL_HOST; + +/** + * @internal + */ +class UrlValidatorUtil +{ + public static function validate(string $url, string $siteUrl): bool + { + $host = parse_url($url, PHP_URL_HOST); + $siteHost = parse_url($siteUrl, PHP_URL_HOST); + + if ($host !== $siteHost) { + return false; + } + + if (!filter_var($url, FILTER_VALIDATE_URL)) { + return false; + } + + if (!str_starts_with($url, $siteUrl)) { + return false; + } + + return true; + } +} diff --git a/tests/unit/Espo/Tools/UserSecurity/Password/UrlValidatorUtilTest.php b/tests/unit/Espo/Tools/UserSecurity/Password/UrlValidatorUtilTest.php new file mode 100644 index 0000000000..8ef985c7e3 --- /dev/null +++ b/tests/unit/Espo/Tools/UserSecurity/Password/UrlValidatorUtilTest.php @@ -0,0 +1,59 @@ +. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. + ************************************************************************/ + +namespace tests\unit\Espo\Tools\UserSecurity\Password; + +use Espo\Tools\UserSecurity\Password\Recovery\UrlValidatorUtil; +use PHPUnit\Framework\TestCase; + +class UrlValidatorUtilTest extends TestCase +{ + public function testValidate(): void + { + $this->assertTrue( + UrlValidatorUtil::validate('https://test.com', 'https://test.com') + ); + + $this->assertTrue( + UrlValidatorUtil::validate('https://test.com/test', 'https://test.com') + ); + + $this->assertTrue( + UrlValidatorUtil::validate('https://test.com/test', 'https://test.com/test') + ); + + $this->assertFalse( + UrlValidatorUtil::validate('https://test.com.test', 'https://test.com') + ); + + $this->assertFalse( + UrlValidatorUtil::validate('https://test.com.test