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
This commit is contained in:
Murat Aslan 2025-11-29 13:38:45 +03:00
parent a56fde7f12
commit 9c680e3b4b

View file

@ -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',