Use parse_url + str_ends_with for endpoint check

Substring matching on the full URL hit false positives in three ways:
the domain in a query string, a `customer.com.attacker.io` suffix attack,
and `fake-customer.com` superstring matches. Parse the host out of the
URL and match against `_APP_DOMAIN` exactly or as a `.`-prefixed suffix
(to allow region subdomains like `fra.localhost`).
This commit is contained in:
Prem Palanisamy
2026-05-22 15:26:48 +01:00
parent a91796db14
commit 2b08313cda
+7 -3
View File
@@ -208,11 +208,15 @@ class Migrations extends Action
$this->sourceProject = $this->dbForPlatform->getDocument('projects', $credentials['projectId']);
// Same projectId on source and destination only means "local" when the source
// endpoint points at this installation — otherwise it's an external Appwrite
// endpoint's host is this installation — otherwise it's an external Appwrite
// that happens to share an id, and we must go over SDK/HTTP.
$sourceHost = parse_url($credentials['endpoint'] ?? '', PHP_URL_HOST);
$localDomain = System::getEnv('_APP_DOMAIN', '');
$isLocalEndpoint = is_string($sourceHost) && $localDomain !== ''
&& ($sourceHost === $localDomain || str_ends_with($sourceHost, '.' . $localDomain));
$isLocalSource = !$this->sourceProject->isEmpty()
&& (!$isAppwriteToAppwrite
|| str_contains($credentials['endpoint'] ?? '', System::getEnv('_APP_DOMAIN', '_')));
&& (!$isAppwriteToAppwrite || $isLocalEndpoint);
if ($isLocalSource) {
$projectDB = call_user_func($this->getProjectDB, $this->sourceProject);