255) { $fail('The :attribute must not exceed 255 characters.'); return; } // Check for path separators (prevent path traversal) if (str_contains($filename, '/') || str_contains($filename, '\\')) { $fail('The :attribute cannot contain path separators.'); return; } // Check for hidden files (starting with dot) if (str_starts_with($filename, '.')) { $fail('The :attribute cannot start with a dot (hidden files not allowed).'); return; } // Check for valid characters only: alphanumeric, dashes, underscores, dots if (! preg_match('/^[a-zA-Z0-9._-]+$/', $filename)) { $fail('The :attribute may only contain letters, numbers, dashes, underscores, and dots.'); return; } // Check for reserved filenames (case-sensitive for coolify.yaml/yml, case-insensitive check not needed as Caddyfile is exact) if (in_array($filename, self::RESERVED_FILENAMES, true)) { $fail('The :attribute uses a reserved filename.'); return; } } }