From da0b2a751757055902e5595d7d7d71bb5ebd4967 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Sun, 14 Dec 2025 22:41:15 +0000 Subject: [PATCH] fix: cors wildcard --- src/Appwrite/Network/Cors.php | 5 ++++- tests/unit/Network/CorsTest.php | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Network/Cors.php b/src/Appwrite/Network/Cors.php index 88d0158379..9fc47c5808 100644 --- a/src/Appwrite/Network/Cors.php +++ b/src/Appwrite/Network/Cors.php @@ -2,6 +2,8 @@ namespace Appwrite\Network; +use Utopia\Validator\Hostname; + /** * Generate CORS response headers for an incoming request. * @@ -76,7 +78,8 @@ final class Cors } // Match only by host - if (!\in_array($host, $this->allowedHosts, true)) { + $validator = new Hostname($this->allowedHosts); + if (!$validator->isValid($host)) { return $headers; } diff --git a/tests/unit/Network/CorsTest.php b/tests/unit/Network/CorsTest.php index 521bf21f1e..986e48ebb5 100644 --- a/tests/unit/Network/CorsTest.php +++ b/tests/unit/Network/CorsTest.php @@ -36,6 +36,21 @@ final class CorsTest extends TestCase $this->assertSame('https://foo.com', $result[Cors::HEADER_ALLOW_ORIGIN]); } + public function testSubdomainWildcardAllowsAnySubdomain(): void + { + $cors = new Cors( + allowedHosts: ['*.example.com'], + allowedMethods: ['GET'], + allowedHeaders: ['X-Test'], + exposedHeaders: [], + allowCredentials: false + ); + + $result = $cors->headers('https://foo.example.com'); + + $this->assertSame('https://foo.example.com', $result[Cors::HEADER_ALLOW_ORIGIN]); + } + public function testEmptyOriginReturnsStaticHeadersOnly(): void { $cors = new Cors(