I've the following "dummy" credentials (username and PAT) for accessing a repository:
bd6164:o6g5xae5fmqeqdbjatdfjichdk55lweq4jxyt2jvwtjuzxdwwgxa
Now, according to MS documentation, I should supply these credentials to git using git -c http.extraHeader="Authorization: Basic <base64>" ..., which results in successful authentication.
However, if I supply these credentials to git directly in the URL:
https://bd6164:o6g5xae5fmqeqdbjatdfjichdk55lweq4jxyt2jvwtjuzxdwwgxa@azuredevops.example.net
then authentication fails.
Normally, when I use git, I can put my credentials directly in the URL for successful authentication, so why do I experience these inconsistencies? In general, aren't credentials in the URL converted to Base64 and sent in a "Authorization: Basic" HTTP header?
Here is the documentation from MS on how to use PAT with git:
https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page#use-a-pat
Works:
# git -c http.extraHeader="Authorization: Basic YmQ2MTY0Om82ZzV4YWU1Zm1xZXFkYmphdGRmamljaGRrNTVsd2VxNGp4eXQyanZ3dGp1enhkd3dneGE=" clone https://azuredevops.example.net/Main/MyProj/_git/MyRepo
Fails:
# git clone https://bd6164:o6g5xae5fmqeqdbjatdfjichdk55lweq4jxyt2jvwtjuzxdwwgxa@azuredevops.example.net/Main/MyProj/_git/MyRepo
Before Git 2.34 (Q4 2021), sensitive data in the HTTP trace were supposed to be redacted, but we failed to do so in HTTP/2 requests.
See commit b66c77a (22 Sep 2021) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster -- in commit 58e2bc4, 03 Oct 2021)
http: match headers case-insensitively when redactingSigned-off-by: Jeff King
When HTTP/2 is in use, we fail to correctly redact "Authorization" (and other) headers in our
GIT_TRACE_CURLoutput.We get the headers in our
CURLOPT_DEBUGFUNCTIONcallback,curl_trace().
It passes them along tocurl_dump_header(), which in turn checksredact_sensitive_header().
We see the headers as a text buffer like:Host: ... Authorization: Basic ...After breaking it into lines, we match each header using
skip_prefix().
This is case-sensitive, even though HTTP headers are case-insensitive.
This has worked reliably in the past because these headers are generated by curl itself, which is predictable in what it sends.But when HTTP/2 is in use, instead we get a lower-case "authorization:" header, and we fail to match it.
The fix is simple: we should match withskip_iprefix().There's one other way to demonstrate the issue (and how I actually found it originally).
Looking atGIT_TRACE_CURLoutput againstgithub.com, you'll see the unredacted output, even if you didn't sethttp.version.
That's because setting it is only necessary for curl to send the extra headers in its HTTP/1.1 request that say "Hey, I speak HTTP/2; upgrade if you do, too".
But for a production site speaking https, the server advertises via ALPN, a TLS extension, that it supports HTTP/2, and the client can immediately start using it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With