903895814a
- Covered webhook SSR allow list useage via test. - Updated allow list handling to use trailing slash, or hash, or end of line as late anchor for better handling for hosts (prevent .co.uk passing for .co domain host)
64 lines
1.4 KiB
PHP
64 lines
1.4 KiB
PHP
<?php
|
|
|
|
namespace BookStack\Util;
|
|
|
|
use BookStack\Exceptions\HttpFetchException;
|
|
|
|
class SsrUrlValidator
|
|
{
|
|
protected string $config;
|
|
|
|
public function __construct(string $config = null)
|
|
{
|
|
$this->config = $config ?? config('app.ssr_hosts') ?? '';
|
|
}
|
|
|
|
/**
|
|
* @throws HttpFetchException
|
|
*/
|
|
public function ensureAllowed(string $url): void
|
|
{
|
|
if (!$this->allowed($url)) {
|
|
throw new HttpFetchException(trans('errors.http_ssr_url_no_match'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if the given URL is allowed by the configured SSR host values.
|
|
*/
|
|
public function allowed(string $url): bool
|
|
{
|
|
$allowed = $this->getHostPatterns();
|
|
|
|
foreach ($allowed as $pattern) {
|
|
if ($this->urlMatchesPattern($url, $pattern)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
protected function urlMatchesPattern($url, $pattern): bool
|
|
{
|
|
$pattern = rtrim(trim($pattern), '/');
|
|
$url = trim($url);
|
|
|
|
if (empty($pattern) || empty($url)) {
|
|
return false;
|
|
}
|
|
|
|
$quoted = preg_quote($pattern, '/');
|
|
$regexPattern = str_replace('\*', '.*', $quoted);
|
|
|
|
return preg_match('/^' . $regexPattern . '($|\/.*$|#.*$)/i', $url);
|
|
}
|
|
|
|
/**
|
|
* @return string[]
|
|
*/
|
|
protected function getHostPatterns(): array
|
|
{
|
|
return explode(' ', strtolower($this->config));
|
|
}
|
|
}
|