<feed xmlns='http://www.w3.org/2005/Atom'>
<title>git/credential.c, branch v2.26.3</title>
<subtitle>Mirror of https://git.kernel.org/pub/scm/git/git.git/
</subtitle>
<id>https://git.shady.money/git/atom?h=v2.26.3</id>
<link rel='self' href='https://git.shady.money/git/atom?h=v2.26.3'/>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/'/>
<updated>2020-04-19T23:32:24Z</updated>
<entry>
<title>Git 2.26.2</title>
<updated>2020-04-19T23:32:24Z</updated>
<author>
<name>Jonathan Nieder</name>
<email>jrnieder@gmail.com</email>
</author>
<published>2020-04-19T23:32:24Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=af6b65d45ef179ed52087e80cb089f6b2349f4ec'/>
<id>urn:sha1:af6b65d45ef179ed52087e80cb089f6b2349f4ec</id>
<content type='text'>
This merges up the security fix from v2.17.5.

Signed-off-by: Jonathan Nieder &lt;jrnieder@gmail.com&gt;
</content>
</entry>
<entry>
<title>Git 2.18.4</title>
<updated>2020-04-19T23:24:14Z</updated>
<author>
<name>Jonathan Nieder</name>
<email>jrnieder@gmail.com</email>
</author>
<published>2020-04-19T23:24:14Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=ba6f0905fdb9e65c1ac5fbc79c9a4ef0b59b3e68'/>
<id>urn:sha1:ba6f0905fdb9e65c1ac5fbc79c9a4ef0b59b3e68</id>
<content type='text'>
This merges up the security fix from v2.17.5.

Signed-off-by: Jonathan Nieder &lt;jrnieder@gmail.com&gt;
</content>
</entry>
<entry>
<title>credential: treat URL with empty scheme as invalid</title>
<updated>2020-04-19T23:10:58Z</updated>
<author>
<name>Jonathan Nieder</name>
<email>jrnieder@gmail.com</email>
</author>
<published>2020-04-19T03:54:57Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=e7fab62b736cca3416660636e46f0be8386a5030'/>
<id>urn:sha1:e7fab62b736cca3416660636e46f0be8386a5030</id>
<content type='text'>
Until "credential: refuse to operate when missing host or protocol",
Git's credential handling code interpreted URLs with empty scheme to
mean "give me credentials matching this host for any protocol".

Luckily libcurl does not recognize such URLs (it tries to look for a
protocol named "" and fails). Just in case that changes, let's reject
them within Git as well. This way, credential_from_url is guaranteed to
always produce a "struct credential" with protocol and host set.

Signed-off-by: Jonathan Nieder &lt;jrnieder@gmail.com&gt;
</content>
</entry>
<entry>
<title>credential: treat URL without scheme as invalid</title>
<updated>2020-04-19T23:10:58Z</updated>
<author>
<name>Jonathan Nieder</name>
<email>jrnieder@gmail.com</email>
</author>
<published>2020-04-19T03:54:13Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=c44088ecc4b0722636e0a305f9608d3047197282'/>
<id>urn:sha1:c44088ecc4b0722636e0a305f9608d3047197282</id>
<content type='text'>
libcurl permits making requests without a URL scheme specified.  In
this case, it guesses the URL from the hostname, so I can run

	git ls-remote http::ftp.example.com/path/to/repo

and it would make an FTP request.

Any user intentionally using such a URL is likely to have made a typo.
Unfortunately, credential_from_url is not able to determine the host and
protocol in order to determine appropriate credentials to send, and
until "credential: refuse to operate when missing host or protocol",
this resulted in another host's credentials being leaked to the named
host.

Teach credential_from_url_gently to consider such a URL to be invalid
so that fsck can detect and block gitmodules files with such URLs,
allowing server operators to avoid serving them to downstream users
running older versions of Git.

This also means that when such URLs are passed on the command line, Git
will print a clearer error so affected users can switch to the simpler
URL that explicitly specifies the host and protocol they intend.

One subtlety: .gitmodules files can contain relative URLs, representing
a URL relative to the URL they were cloned from.  The relative URL
resolver used for .gitmodules can follow ".." components out of the path
part and past the host part of a URL, meaning that such a relative URL
can be used to traverse from a https://foo.example.com/innocent
superproject to a https::attacker.example.com/exploit submodule.
Fortunately a leading ':' in the first path component after a series of
leading './' and '../' components is unlikely to show up in other
contexts, so we can catch this by detecting that pattern.

Reported-by: Jeff King &lt;peff@peff.net&gt;
Signed-off-by: Jonathan Nieder &lt;jrnieder@gmail.com&gt;
Reviewed-by: Jeff King &lt;peff@peff.net&gt;
</content>
</entry>
<entry>
<title>credential: die() when parsing invalid urls</title>
<updated>2020-04-19T23:10:58Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2020-04-19T03:53:09Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=fe29a9b7b0236d3d45c254965580d6aff7fa8504'/>
<id>urn:sha1:fe29a9b7b0236d3d45c254965580d6aff7fa8504</id>
<content type='text'>
When we try to initialize credential loading by URL and find that the
URL is invalid, we set all fields to NULL in order to avoid acting on
malicious input. Later when we request credentials, we diagonse the
erroneous input:

	fatal: refusing to work with credential missing host field

This is problematic in two ways:

- The message doesn't tell the user *why* we are missing the host
  field, so they can't tell from this message alone how to recover.
  There can be intervening messages after the original warning of
  bad input, so the user may not have the context to put two and two
  together.

- The error only occurs when we actually need to get a credential.  If
  the URL permits anonymous access, the only encouragement the user gets
  to correct their bogus URL is a quiet warning.

  This is inconsistent with the check we perform in fsck, where any use
  of such a URL as a submodule is an error.

When we see such a bogus URL, let's not try to be nice and continue
without helpers. Instead, die() immediately. This is simpler and
obviously safe. And there's very little chance of disrupting a normal
workflow.

It's _possible_ that somebody has a legitimate URL with a raw newline in
it. It already wouldn't work with credential helpers, so this patch
steps that up from an inconvenience to "we will refuse to work with it
at all". If such a case does exist, we should figure out a way to work
with it (especially if the newline is only in the path component, which
we normally don't even pass to helpers). But until we see a real report,
we're better off being defensive.

Reported-by: Carlo Arenas &lt;carenas@gmail.com&gt;
Signed-off-by: Jeff King &lt;peff@peff.net&gt;
Signed-off-by: Jonathan Nieder &lt;jrnieder@gmail.com&gt;
</content>
</entry>
<entry>
<title>credential: refuse to operate when missing host or protocol</title>
<updated>2020-04-19T23:10:58Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2020-04-19T03:50:48Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=8ba8ed568e2a3b75ee84c49ddffb026fde1a0a91'/>
<id>urn:sha1:8ba8ed568e2a3b75ee84c49ddffb026fde1a0a91</id>
<content type='text'>
The credential helper protocol was designed to be very flexible: the
fields it takes as input are treated as a pattern, and any missing
fields are taken as wildcards. This allows unusual things like:

  echo protocol=https | git credential reject

to delete all stored https credentials (assuming the helpers themselves
treat the input that way). But when helpers are invoked automatically by
Git, this flexibility works against us. If for whatever reason we don't
have a "host" field, then we'd match _any_ host. When you're filling a
credential to send to a remote server, this is almost certainly not what
you want.

Prevent this at the layer that writes to the credential helper. Add a
check to the credential API that the host and protocol are always passed
in, and add an assertion to the credential_write function that speaks
credential helper protocol to be doubly sure.

There are a few ways this can be triggered in practice:

  - the "git credential" command passes along arbitrary credential
    parameters it reads from stdin.

  - until the previous patch, when the host field of a URL is empty, we
    would leave it unset (rather than setting it to the empty string)

  - a URL like "example.com/foo.git" is treated by curl as if "http://"
    was present, but our parser sees it as a non-URL and leaves all
    fields unset

  - the recent fix for URLs with embedded newlines blanks the URL but
    otherwise continues. Rather than having the desired effect of
    looking up no credential at all, many helpers will return _any_
    credential

Our earlier test for an embedded newline didn't catch this because it
only checked that the credential was cleared, but didn't configure an
actual helper. Configuring the "verbatim" helper in the test would show
that it is invoked (it's obviously a silly helper which doesn't look at
its input, but the point is that it shouldn't be run at all). Since
we're switching this case to die(), we don't need to bother with a
helper. We can see the new behavior just by checking that the operation
fails.

We'll add new tests covering partial input as well (these can be
triggered through various means with url-parsing, but it's simpler to
just check them directly, as we know we are covered even if the url
parser changes behavior in the future).

[jn: changed to die() instead of logging and showing a manual
 username/password prompt]

Reported-by: Carlo Arenas &lt;carenas@gmail.com&gt;
Signed-off-by: Jeff King &lt;peff@peff.net&gt;
Signed-off-by: Jonathan Nieder &lt;jrnieder@gmail.com&gt;
</content>
</entry>
<entry>
<title>credential: parse URL without host as empty host, not unset</title>
<updated>2020-04-19T23:10:57Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2020-04-19T03:48:05Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=24036686c4af84c9e84e486ef3debab6e6d8e6b5'/>
<id>urn:sha1:24036686c4af84c9e84e486ef3debab6e6d8e6b5</id>
<content type='text'>
We may feed a URL like "cert:///path/to/cert.pem" into the credential
machinery to get the key for a client-side certificate. That
credential has no hostname field, which is about to be disallowed (to
avoid confusion with protocols where a helper _would_ expect a
hostname).

This means as of the next patch, credential helpers won't work for
unlocking certs. Let's fix that by doing two things:

  - when we parse a url with an empty host, set the host field to the
    empty string (asking only to match stored entries with an empty
    host) rather than NULL (asking to match _any_ host).

  - when we build a cert:// credential by hand, similarly assign an
    empty string

It's the latter that is more likely to impact real users in practice,
since it's what's used for http connections. But we don't have good
infrastructure to test it.

The url-parsing version will help anybody using git-credential in a
script, and is easy to test.

Signed-off-by: Jeff King &lt;peff@peff.net&gt;
Reviewed-by: Taylor Blau &lt;me@ttaylorr.com&gt;
Signed-off-by: Jonathan Nieder &lt;jrnieder@gmail.com&gt;
</content>
</entry>
<entry>
<title>Git 2.26.1</title>
<updated>2020-03-25T20:07:47Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2020-03-25T20:07:47Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=de49261b050d9cd8ec73842356077bc5b606640f'/>
<id>urn:sha1:de49261b050d9cd8ec73842356077bc5b606640f</id>
<content type='text'>
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>Git 2.18.3</title>
<updated>2020-03-17T20:34:12Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2020-03-17T20:34:12Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=21a3e5016bb218dc9b016284c88ba685bc446b70'/>
<id>urn:sha1:21a3e5016bb218dc9b016284c88ba685bc446b70</id>
<content type='text'>
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>credential: detect unrepresentable values when parsing urls</title>
<updated>2020-03-12T06:55:24Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2020-03-12T05:31:11Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=c716fe4bd917e013bf376a678b3a924447777b2d'/>
<id>urn:sha1:c716fe4bd917e013bf376a678b3a924447777b2d</id>
<content type='text'>
The credential protocol can't represent newlines in values, but URLs can
embed percent-encoded newlines in various components. A previous commit
taught the low-level writing routines to die() when encountering this,
but we can be a little friendlier to the user by detecting them earlier
and handling them gracefully.

This patch teaches credential_from_url() to notice such components,
issue a warning, and blank the credential (which will generally result
in prompting the user for a username and password). We blank the whole
credential in this case. Another option would be to blank only the
invalid component. However, we're probably better off not feeding a
partially-parsed URL result to a credential helper. We don't know how a
given helper would handle it, so we're better off to err on the side of
matching nothing rather than something unexpected.

The die() call in credential_write() is _probably_ impossible to reach
after this patch. Values should end up in credential structs only by URL
parsing (which is covered here), or by reading credential protocol input
(which by definition cannot read a newline into a value). But we should
definitely keep the low-level check, as it's our final and most accurate
line of defense against protocol injection attacks. Arguably it could
become a BUG(), but it probably doesn't matter much either way.

Note that the public interface of credential_from_url() grows a little
more than we need here. We'll use the extra flexibility in a future
patch to help fsck catch these cases.
</content>
</entry>
</feed>
