Skip to content

Commit 06deef7

Browse files
abnegateclaude
andcommitted
(refactor): Use utopia validators for hostname, IP, port, and TLS path validation
- Replace custom isValidHostname() regex with Utopia\Validator\Hostname in both HTTP servers - Use Utopia\Validator\Range for port validation in Adapter::validate() - Use Utopia\Validator\IP for IP format validation in Adapter::validate() - Use Utopia\Validator\Text for TLS certificate path validation - Add utopia-php/validators dependency Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 87543e4 commit 06deef7

5 files changed

Lines changed: 28 additions & 15 deletions

File tree

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"php": ">=8.4",
1414
"ext-redis": "*",
1515
"ext-swoole": ">=6.0",
16-
"utopia-php/console": "^0.1.1"
16+
"utopia-php/console": "^0.1.1",
17+
"utopia-php/validators": "^0.2.0"
1718
},
1819
"require-dev": {
1920
"phpunit/phpunit": "12.*",

src/Adapter.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use Swoole\Table;
66
use Utopia\Proxy\Resolver\Exception as ResolverException;
7+
use Utopia\Validator\IP;
8+
use Utopia\Validator\Range;
79

810
/**
911
* Protocol Proxy Adapter
@@ -277,16 +279,16 @@ protected function validate(string $endpoint): string
277279
$hasPort = isset($parts[1]);
278280
$port = $hasPort ? (int) $parts[1] : 0;
279281

280-
if ($hasPort && ($port < 1 || $port > 65535)) {
282+
if ($hasPort && !(new Range(1, 65535))->isValid($port)) {
281283
throw new ResolverException("Invalid port number: {$port}");
282284
}
283285

284286
$ip = \gethostbyname($host);
285-
if ($ip === $host && !\filter_var($ip, FILTER_VALIDATE_IP)) {
287+
if ($ip === $host && !(new IP())->isValid($ip)) {
286288
throw new ResolverException("Cannot resolve hostname: {$host}");
287289
}
288290

289-
if (\filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
291+
if ((new IP(IP::V4))->isValid($ip)) {
290292
$longIp = \ip2long($ip);
291293
if ($longIp === false) {
292294
throw new ResolverException("Invalid IP address: {$ip}");
@@ -310,7 +312,7 @@ protected function validate(string $endpoint): string
310312
throw new ResolverException("Access to private/reserved IP address is forbidden: {$ip}");
311313
}
312314
}
313-
} elseif (\filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
315+
} elseif ((new IP(IP::V6))->isValid($ip)) {
314316
if (
315317
$ip === '::1'
316318
|| \str_starts_with($ip, 'fe80:')

src/Server/HTTP/Swoole.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Utopia\Proxy\Adapter;
1414
use Utopia\Proxy\Protocol;
1515
use Utopia\Proxy\Resolver;
16+
use Utopia\Validator\Hostname;
1617

1718
/**
1819
* High-performance HTTP proxy server (Swoole Implementation)
@@ -468,11 +469,7 @@ protected function isValidHostname(string $hostname): bool
468469
return false;
469470
}
470471

471-
if (strlen($host) > 255 || preg_match('/[\x00-\x1f\x7f\s]/', $host)) {
472-
return false;
473-
}
474-
475-
return preg_match('/^[a-z0-9]([a-z0-9.-]*[a-z0-9])?$/i', $host) === 1;
472+
return (new Hostname())->isValid($host);
476473
}
477474

478475
public function start(): void

src/Server/HTTP/SwooleCoroutine.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Utopia\Proxy\Adapter;
1414
use Utopia\Proxy\Protocol;
1515
use Utopia\Proxy\Resolver;
16+
use Utopia\Validator\Hostname;
1617

1718
/**
1819
* High-performance HTTP proxy server (Swoole Coroutine Implementation)
@@ -470,11 +471,7 @@ protected function isValidHostname(string $hostname): bool
470471
return false;
471472
}
472473

473-
if (strlen($host) > 255 || preg_match('/[\x00-\x1f\x7f\s]/', $host)) {
474-
return false;
475-
}
476-
477-
return preg_match('/^[a-z0-9]([a-z0-9.-]*[a-z0-9])?$/i', $host) === 1;
474+
return (new Hostname())->isValid($host);
478475
}
479476

480477
public function start(): void

src/Server/TCP/TLS.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Utopia\Proxy\Server\TCP;
44

5+
use Utopia\Validator\Text;
6+
57
/**
68
* TLS Configuration for TCP Proxy Server
79
*
@@ -77,10 +79,20 @@ public function __construct(
7779
*/
7880
public function validate(): void
7981
{
82+
$path = new Text(4096);
83+
84+
if (!$path->isValid($this->certificate)) {
85+
throw new \RuntimeException("TLS certificate path is invalid: {$path->getDescription()}");
86+
}
87+
8088
if (!is_readable($this->certificate)) {
8189
throw new \RuntimeException("TLS certificate file not readable: {$this->certificate}");
8290
}
8391

92+
if (!$path->isValid($this->key)) {
93+
throw new \RuntimeException("TLS key path is invalid: {$path->getDescription()}");
94+
}
95+
8496
if (!is_readable($this->key)) {
8597
throw new \RuntimeException("TLS private key file not readable: {$this->key}");
8698
}
@@ -89,6 +101,10 @@ public function validate(): void
89101
throw new \RuntimeException('CA certificate path is required when client certificate verification is enabled');
90102
}
91103

104+
if ($this->ca !== '' && !$path->isValid($this->ca)) {
105+
throw new \RuntimeException("TLS CA path is invalid: {$path->getDescription()}");
106+
}
107+
92108
if ($this->ca !== '' && !is_readable($this->ca)) {
93109
throw new \RuntimeException("TLS CA certificate file not readable: {$this->ca}");
94110
}

0 commit comments

Comments
 (0)