From 9c680e3b4b6a7257f1111708a668ca73da37468f Mon Sep 17 00:00:00 2001 From: Murat Aslan Date: Sat, 29 Nov 2025 13:38:45 +0300 Subject: [PATCH] fix: URL encode basic auth credentials in Git HTTP URLs When using HTTP(S) Git URLs with basic authentication, special characters in username or password (like @ in email addresses) were not being URL encoded, causing git clone to fail. For example: - Before: https://user@email.com:pass@git.example.com/repo.git (fails) - After: https://user%40email.com:pass@git.example.com/repo.git (works) The fix automatically encodes credentials using rawurlencode() while preserving already-encoded values with rawurldecode() first. Fixes #5295 --- bootstrap/helpers/shared.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 1066f1a63..fee3e2771 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -3047,6 +3047,34 @@ NGINX; function convertGitUrl(string $gitRepository, string $deploymentType, ?GithubApp $source = null): array { $repository = $gitRepository; + + // URL encode basic auth credentials in HTTP(S) URLs to handle special characters like @ in usernames + if (preg_match('/^https?:\/\//', $gitRepository)) { + $parsedUrl = parse_url($gitRepository); + if ($parsedUrl !== false && (isset($parsedUrl['user']) || isset($parsedUrl['pass']))) { + $host = $parsedUrl['host'] ?? ''; + if ($host !== '') { + $scheme = $parsedUrl['scheme'] ?? 'https'; + $port = isset($parsedUrl['port']) ? ':'.$parsedUrl['port'] : ''; + $path = $parsedUrl['path'] ?? ''; + $query = isset($parsedUrl['query']) ? '?'.$parsedUrl['query'] : ''; + $fragment = isset($parsedUrl['fragment']) ? '#'.$parsedUrl['fragment'] : ''; + + // Re-wrap IPv6 hosts with brackets (parse_url strips them) + $isIpv6 = str_contains($host, ':'); + $hostFormatted = $isIpv6 ? '['.$host.']' : $host; + + $user = isset($parsedUrl['user']) ? rawurlencode(rawurldecode($parsedUrl['user'])) : ''; + $pass = isset($parsedUrl['pass']) ? ':'.rawurlencode(rawurldecode($parsedUrl['pass'])) : ''; + $hasAuth = ($user !== '' || $pass !== ''); + $auth = $hasAuth ? $user.$pass.'@' : ''; + + $repository = $scheme.'://'.$auth.$hostFormatted.$port.$path.$query.$fragment; + $gitRepository = $repository; + } + } + } + $providerInfo = [ 'host' => null, 'user' => 'git',