* [BUG] http: push with token-only URL userinfo fails after libcurl strips creds from CURLINFO_EFFECTIVE_URL
@ 2026-10-16 22:36 Dan
2026-10-21 11:23 ` Tuomas Ahola
0 siblings, 1 reply; 2+ messages in thread
From: Dan @ 2026-10-16 22:36 UTC (permalink / raw)
To: git
Hi,
(Please note this was done with the assistance of Claude, I apologize
if there are inaccuracies here, Ive tried to go over this and verify
as much of it as I am capable of. I tried looking at the mailing list
archives to see if this has already been reported and I didnt see
anything that looked like it had yet. I can verify that the new
libcurl behavior absolutely seems to be causing issues from at least
my own limited vantage point. -Dan)
Since libcurl stopped returning credentials in CURLINFO_EFFECTIVE_URL
(curl 8.23.0, commit 7a6bd027d0de "getinfo: make sure
CURLINFO_EFFECTIVE_URL does not contain creds", CVE-2026-94266; also
backported to Ubuntu 24.04 as curl 8.5.0-2ubuntu10.16, USN-8932-1),
pushing over smart HTTP fails when the remote URL carries a username
but no password, e.g.
https://<token>@forge.example/owner/repo.git
which is a common way for CI tools to pass an access token (Renovate
does this for Gitea/Forgejo). Fetch/clone keep working; push does not.
Versions
--------
git 2.55.0 (1:2.55.0-0ppa1~ubuntu24.04.2)
libcurl3t64-gnutls 8.5.0-2ubuntu10.16 -> fails
libcurl3t64-gnutls 8.5.0-2ubuntu10.15 -> works (same git build)
Server: Forgejo 16.0.6 (answers the first unauthenticated request
with 401 + "WWW-Authenticate: Basic realm=...")
Reproduce
---------
git clone https://<token>@forge.example/owner/repo.git && cd repo
git commit --allow-empty -m test
GIT_TERMINAL_PROMPT=0 git push origin HEAD:refs/heads/test
Expected: push succeeds (it did with the previous libcurl).
Actual:
Pushing to https://forge.example/owner/repo.git
warning: redirecting to https://forge.example/owner/repo.git/
POST git-receive-pack (815 bytes)
fatal: could not read Username for 'https://forge.example': No such
device or address
send-pack: unexpected disconnect while reading sideband packet
fatal: the remote end hung up unexpectedly
No redirect happens on the server side; the server log shows
GET info/refs 401 -> GET info/refs 200 -> POST git-receive-pack 401.
GIT_TRACE_CURL (abridged, credentials redacted):
=> Send header: GET /owner/repo.git/info/refs?service=git-receive-pack HTTP/2
<= Recv header: HTTP/2 401
<= Recv header: www-authenticate: Basic realm="Gitea"
== Info: Issue another request to this URL:
'https://<cred>@forge.example/owner/repo.git/info/refs?service=git-receive-pack'
== Info: Server auth using Basic with user '<redacted>'
=> Send header: GET /owner/repo.git/info/refs?service=git-receive-pack HTTP/2
=> Send header: Authorization: <redacted>
<= Recv header: HTTP/2 200
warning: redirecting to https://forge.example/owner/repo.git/
== Info: [HTTP/2] [5] OPENED stream for
https://forge.example/owner/repo.git/git-receive-pack
=> Send header: POST /owner/repo.git/git-receive-pack HTTP/2
(no Authorization header)
<= Recv header: HTTP/2 401
Analysis
--------
In http.c, http_request_reauth() calls update_url_from_redirect() with
the URL git asked for and CURLINFO_EFFECTIVE_URL. The asked-for URL
still contains "<token>@", but libcurl now returns the effective URL
without userinfo, so the strcmp() differs and git treats an ordinary
200 as a redirect: it prints "redirecting to ...", rewrites base_url to
the credential-less URL and calls credential_from_url(&http_auth, ...)
on it, which credential_clear()s http_auth.
With a username-only URL, http_auth.password was never set, so
init_curl_http_auth() never put CURLOPT_USERNAME/PASSWORD on the handle;
the only auth curl had was the userinfo in the URL. Once the URL is
rewritten, the POST goes out with no credentials, gets 401, and
credential_fill() has nothing to fill from (http_auth was cleared,
no helper, no terminal), hence "could not read Username".
With "user:password@" in the URL the same false redirect happens, but
the push still succeeded in my test - presumably because
init_curl_http_auth() had already set CURLOPT_USERNAME/PASSWORD on the
reused handle before http_auth was cleared.
Possible fix
------------
Compare the URLs without userinfo in update_url_from_redirect() (strip
"user[:pass]@" from the asked-for URL, or from both, before the
strcmp/skip_prefix), so a credential-free effective URL that is
otherwise identical is not treated as a redirect. For a real redirect
on the same origin, keeping the existing http_auth instead of
re-parsing it from a credential-less URL would also avoid losing the
username. I haven't written or tested a patch.
Workaround for users: use "user:token@" instead of "token@" in the URL,
or provide the token through a credential helper.
Thanks,
Daniel Spisak
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [BUG] http: push with token-only URL userinfo fails after libcurl strips creds from CURLINFO_EFFECTIVE_URL
2026-10-16 22:36 [BUG] http: push with token-only URL userinfo fails after libcurl strips creds from CURLINFO_EFFECTIVE_URL Dan
@ 2026-10-21 11:23 ` Tuomas Ahola
0 siblings, 0 replies; 2+ messages in thread
From: Tuomas Ahola @ 2026-10-21 11:23 UTC (permalink / raw)
To: Dan; +Cc: git
Dan <timelord@gmail.com> wrote:
> Hi,
>
> (Please note this was done with the assistance of Claude, I apologize
> if there are inaccuracies here, Ive tried to go over this and verify
> as much of it as I am capable of. I tried looking at the mailing list
> archives to see if this has already been reported and I didnt see
> anything that looked like it had yet. I can verify that the new
> libcurl behavior absolutely seems to be causing issues from at least
> my own limited vantage point. -Dan)
>
> Since libcurl stopped returning credentials in CURLINFO_EFFECTIVE_URL
> (curl 8.23.0, commit 7a6bd027d0de "getinfo: make sure
> CURLINFO_EFFECTIVE_URL does not contain creds", CVE-2026-94266; also
> backported to Ubuntu 24.04 as curl 8.5.0-2ubuntu10.16, USN-8932-1),
> pushing over smart HTTP fails when the remote URL carries a username
> but no password, e.g.
>
> https://<token>@forge.example/owner/repo.git
>
> which is a common way for CI tools to pass an access token (Renovate
> does this for Gitea/Forgejo). Fetch/clone keep working; push does not.
>
Thanks. Please check if 76524c2604 (http: handle curl stripping creds from
effective url, 2026-09-28) works for you. The patch is already merged to
'master', and is described in the release notes as:
* The HTTP transport has been updated to handle changes in recent curl
versions that strip credentials from the effective URL, preventing
unnecessary credential prompts during redirects.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-21 11:23 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 22:36 [BUG] http: push with token-only URL userinfo fails after libcurl strips creds from CURLINFO_EFFECTIVE_URL Dan
2026-10-21 11:23 ` Tuomas Ahola
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox