mirror of
https://github.com/tiennm99/coolify.git
synced 2026-08-20 00:23:27 +00:00
Split V5 dashboard behavior into domain controllers and policies, add agent token rotation/revocation, status reconciliation jobs, ingress firewall syncing, and canvas connection APIs. Add migrations for V5 status tracking, server capabilities, resource connection aliases, and revoked agent tokens.
127 lines
4.4 KiB
PHP
127 lines
4.4 KiB
PHP
<?php
|
|
|
|
namespace App\Rules;
|
|
|
|
use Closure;
|
|
use Illuminate\Contracts\Validation\ValidationRule;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class ValidHostname implements ValidationRule
|
|
{
|
|
/**
|
|
* Run the validation rule.
|
|
*
|
|
* Validates hostname according to RFC 1123:
|
|
* - Must be 1-253 characters total
|
|
* - Each label (segment between dots) must be 1-63 characters
|
|
* - Labels can contain lowercase letters (a-z), digits (0-9), and hyphens (-)
|
|
* - Labels cannot start or end with a hyphen
|
|
* - Labels cannot be all numeric
|
|
*/
|
|
public function validate(string $attribute, mixed $value, Closure $fail): void
|
|
{
|
|
if (empty($value)) {
|
|
return;
|
|
}
|
|
|
|
$hostname = trim($value);
|
|
|
|
// Check total length (RFC 1123: max 253 characters)
|
|
if (strlen($hostname) > 253) {
|
|
$fail('The :attribute must not exceed 253 characters.');
|
|
|
|
return;
|
|
}
|
|
|
|
// Reject ASCII control characters (including embedded newlines, which
|
|
// would otherwise slip through the trailing-newline-tolerant `$` anchor
|
|
// in the per-label regex below).
|
|
if (preg_match('/[\x00-\x1f\x7f]/', $hostname) === 1) {
|
|
$fail('The :attribute contains invalid characters. Only letters (a-z, A-Z), numbers (0-9), hyphens (-), and dots (.) are allowed.');
|
|
|
|
return;
|
|
}
|
|
|
|
// Check for dangerous shell metacharacters
|
|
$dangerousChars = [
|
|
';', '|', '&', '$', '`', '(', ')', '{', '}',
|
|
'<', '>', "\n", "\r", "\0", '"', "'", '\\',
|
|
'!', '*', '?', '[', ']', '~', '^', ':', '#',
|
|
'@', '%', '=', '+', ',', ' ',
|
|
];
|
|
|
|
foreach ($dangerousChars as $char) {
|
|
if (str_contains($hostname, $char)) {
|
|
try {
|
|
$logData = [
|
|
'hostname' => $hostname,
|
|
'character' => $char,
|
|
];
|
|
|
|
if (function_exists('request') && app()->has('request')) {
|
|
$logData['ip'] = request()->ip();
|
|
}
|
|
|
|
if (function_exists('auth') && app()->has('auth')) {
|
|
$logData['user_id'] = auth()->id();
|
|
}
|
|
|
|
Log::warning('Hostname validation failed - dangerous character', $logData);
|
|
} catch (\Throwable $e) {
|
|
// Ignore errors when facades are not available (e.g., in unit tests)
|
|
}
|
|
|
|
$fail('The :attribute contains invalid characters. Only letters (a-z, A-Z), numbers (0-9), hyphens (-), and dots (.) are allowed.');
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Normalize to lowercase for validation (RFC 1123 hostnames are case-insensitive)
|
|
$hostname = strtolower($hostname);
|
|
|
|
// Additional validation: hostname should not start or end with a dot
|
|
if (str_starts_with($hostname, '.') || str_ends_with($hostname, '.')) {
|
|
$fail('The :attribute cannot start or end with a dot.');
|
|
|
|
return;
|
|
}
|
|
|
|
// Check for consecutive dots
|
|
if (str_contains($hostname, '..')) {
|
|
$fail('The :attribute cannot contain consecutive dots.');
|
|
|
|
return;
|
|
}
|
|
|
|
// Split into labels (segments between dots)
|
|
$labels = explode('.', $hostname);
|
|
|
|
foreach ($labels as $label) {
|
|
// Check label length (RFC 1123: max 63 characters per label)
|
|
if (strlen($label) < 1 || strlen($label) > 63) {
|
|
$fail('The :attribute contains an invalid label. Each segment must be 1-63 characters.');
|
|
|
|
return;
|
|
}
|
|
|
|
// Check if label starts or ends with hyphen
|
|
if (str_starts_with($label, '-') || str_ends_with($label, '-')) {
|
|
$fail('The :attribute contains an invalid label. Labels cannot start or end with a hyphen.');
|
|
|
|
return;
|
|
}
|
|
|
|
// Check if label contains only valid characters (letters, digits, hyphens)
|
|
if (! preg_match('/^[a-z0-9-]+$/D', $label)) {
|
|
$fail('The :attribute contains invalid characters. Only letters (a-z, A-Z), numbers (0-9), hyphens (-), and dots (.) are allowed.');
|
|
|
|
return;
|
|
}
|
|
|
|
// RFC 1123 allows labels to be all numeric (unlike RFC 952)
|
|
// So we don't need to check for all-numeric labels
|
|
}
|
|
}
|
|
}
|