fix(domains): reject non-HTTP URL schemes

This commit is contained in:
Andras Bacsai 2026-07-07 12:20:26 +02:00
parent 74b1077010
commit bce871d991
2 changed files with 51 additions and 6 deletions

View file

@ -6,12 +6,50 @@
function isValidDomainUrl(string $url): bool
{
// PHP's FILTER_VALIDATE_URL rejects underscores in the host, but they are
// accepted by browsers, Let's Encrypt, and common Docker service naming
// (e.g. https://myapp_service.example.com). Validate against a copy with
// underscores replaced by hyphens (a valid host character) so such domains
// are not wrongly rejected; URLs without underscores are unaffected.
return filter_var(str_replace('_', '-', $url), FILTER_VALIDATE_URL) !== false;
$components = parse_url($url);
if ($components === false) {
return false;
}
$scheme = $components['scheme'] ?? '';
$host = $components['host'] ?? '';
if (! in_array(strtolower($scheme), ['http', 'https'], true) || $host === '') {
return false;
}
$urlToValidate = $scheme.'://';
if (isset($components['user'])) {
$urlToValidate .= $components['user'];
if (isset($components['pass'])) {
$urlToValidate .= ':'.$components['pass'];
}
$urlToValidate .= '@';
}
$urlToValidate .= str_replace('_', '-', $host);
if (isset($components['port'])) {
$urlToValidate .= ':'.$components['port'];
}
if (isset($components['path'])) {
$urlToValidate .= $components['path'];
}
if (isset($components['query'])) {
$urlToValidate .= '?'.$components['query'];
}
if (isset($components['fragment'])) {
$urlToValidate .= '#'.$components['fragment'];
}
return filter_var($urlToValidate, FILTER_VALIDATE_URL) !== false;
}
function checkDomainUsage(ServiceApplication|Application|null $resource = null, ?string $domain = null)

View file

@ -18,5 +18,12 @@
it('rejects strings that are not valid URLs', function () {
expect(isValidDomainUrl('not a url'))->toBeFalse();
expect(isValidDomainUrl('example.com'))->toBeFalse();
expect(isValidDomainUrl('ht_tp://example.com'))->toBeFalse();
expect(isValidDomainUrl(''))->toBeFalse();
});
it('rejects URLs that do not use HTTP or HTTPS schemes', function () {
expect(isValidDomainUrl('ftp://example.com'))->toBeFalse();
expect(isValidDomainUrl('javascript://example.com'))->toBeFalse();
expect(isValidDomainUrl('data://example.com'))->toBeFalse();
});