To be clear, using credentials in a remote URL like https://you:password@github.com/you/example.git
is not the best practice, and the user should be reminded of that.
Git 2.37 (Q3 2022) offers such a warning: the "transfer.credentialsInUrl
fetch.credentialsInUrl
" configuration variable controls what happens when a URL with embedded login credential is used.
It was initially called fetch.credentialsInUrl
:
See commit 6dcbdc0 (06 Jun 2022) by Derrick Stolee (derrickstolee
).
(Merged by Junio C Hamano -- gitster
-- in commit 11698e5, 13 Jun 2022)
remote
: create fetch.credentialsInUrl config
Helped-by: Junio C Hamano
Signed-off-by: Derrick Stolee
Users sometimes provide a "username:password
" combination in their plaintext URLs.
Since Git stores these URLs in plaintext in the .git/config
file, this is a very insecure way of storing these credentials.
Credential managers are a more secure way of storing this information.
System administrators might want to prevent this kind of use by users on their machines.
Create a new "fetch.credentialsInUrl
" config option and teach Git to warn or die when seeing a URL with this kind of information.
The warning anonymizes the sensitive information of the URL to be clear about the issue.
(again, renamed below as transfer.credentialsInUrl
)
This change currently defaults the behavior to "allow
" which does nothing with these URLs.
We can consider changing this behavior to "warn" by default if we wish.
At that time, we may want to add some advice about setting fetch.credentialsInUrl=ignore
for users who still want to follow this pattern (and not receive the warning).
An earlier version of this change injected the logic into url_normalize()
in urlmatch.c
.
While most code paths that parse URLs eventually normalize the URL, that normalization does not happen early enough in the stack to avoid attempting connections to the URL first.
By inserting a check into the remote validation, we identify the issue before making a connection.
However, we can reuse the parsing information from url_normalize()
in order to benefit from its well-worn parsing logic.
We can use the struct url_info
that is created in that method to replace the password with "<redacted>
" in our error messages.
This comes with a slight downside that the normalized URL might look slightly different from the input URL (for instance, the normalized version adds a closing slash).
This should not hinder users figuring out what the problem is and being able to fix the issue.
As an attempt to ensure the parsing logic did not catch any unintentional cases, I modified this change locally to to use the "die" option by default.
Running the test suite succeeds except for the explicit username:password URLs used in t5550-http-fetch-dumb.sh and t5541-http-push-smart.sh.
This means that all other tested URLs did not trigger this logic.
The tests show that the proper error messages appear (or do not appear), but also count the number of error messages.
When only warning, each process validates the remote URL and outputs a warning.
This happens twice for clone, three times for fetch, and once for push.
The warning or error will be:
URL '%s' uses plaintext credentials
With Git 2.37 (Q3 2022), rename fetch.credentialsInUrl
to transfer.credentialsInUrl
as the single configuration variable should work both in pushing and fetching.
See commit 7281c19, commit 4a169da (15 Jun 2022) by Ævar Arnfjörð Bjarmason (avar
).
(Merged by Junio C Hamano -- gitster
-- in commit 7f5a382, 17 Jun 2022)
transfer doc
: move fetch.credentialsInUrl to "transfer" config namespace
Signed-off-by: Ævar Arnfjörð Bjarmason
Acked-by: Derrick Stolee
Rename the "fetch.credentialsInUrl" configuration variable introduced in 6dcbdc0 ("remote
: create fetch.credentialsInUrl config", 2022-06-06, Git v2.37.0-rc0 -- merge) to "transfer".
There are existing exceptions, but generally speaking the "<namespace>.<var>
" configuration should only apply to command described in the "namespace" (and its sub-commands, so e.g. "clone." or "fetch." might also configure "git-remote-https").
But in the case of "fetch.credentialsInUrl" we've got a configuration variable that configures the behavior of all of "clone", "push" and "fetch", someone adjusting "fetch.*" configuration won't expect to have the behavior of "git push
"(man) altered, especially as we have the pre-existing "{transfer,fetch,receive}.fsckObjects
", which configures different parts of the transfer dialog.
So let's move this configuration variable to the "transfer
" namespace before it's exposed in a release.
We could add all of "{transfer,fetch,pull}.credentialsInUrl
" at some other time, but once we have "fetch
" configure "pull
" such an arrangement would would be a confusing mess, as we'd at least need to have "fetch
" configure "push
" (but not the other way around), or change existing behavior.
git config
now includes in its man page:
transfer.credentialsInUrl
A configured URL can contain plaintext credentials in the form
<protocol>://<user>:<password>@<domain>/<path>
.
You may want
to warn or forbid the use of such configuration (in favor of
using git credential
). >
This will be used on
git clone
, git fetch
, git push
,
and any other direct use of the configured URL.
Note that this is currently limited to detecting credentials in
remote.<name>.url
configuration, it won't detect credentials in
remote.<name>.pushurl
configuration.
You might want to enable this to prevent inadvertent credentials
exposure, e.g. because:
- The OS or system where you're running git may not provide way way or
otherwise allow you to configure the permissions of the
configuration file where the username and/or password are stored.
- Even if it does, having such data stored "at rest" might expose you
in other ways, e.g. a backup process might copy the data to another
system.
- The git programs will pass the full URL to one another as arguments
on the command-line, meaning the credentials will be exposed to oher
users on OS's or systems that allow other users to see the full
process list of other users. On linux the "hidepid" setting
documented in procfs(5) allows for configuring this behavior.
If such concerns don't apply to you then you probably don't need to be
concerned about credentials exposure due to storing that sensitive
data in git's configuration files.
If you do want to use this, set
transfer.credentialsInUrl
to one of these values:
allow
(default): Git will proceed with its activity without warning.
warn
: Git will write a warning message to stderr
when parsing a URL
with a plaintext credential.
die
: Git will write a failure message to stderr
when parsing a URL
with a plaintext credential.