git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Fwd: [Bug] `credential fill` prints incomplete bearer credential
       [not found] <CAGJzqs=ksKqY2M8Px3uv6ut=MBwkmpPUqp3xVzVpNMJ0YBrBww@mail.gmail.com>
@ 2024-12-18 20:42 ` M Hickford
  2024-12-19  2:02   ` brian m. carlson
  0 siblings, 1 reply; 6+ messages in thread
From: M Hickford @ 2024-12-18 20:42 UTC (permalink / raw)
  To: Git Mailing List; +Cc: brian m. carlson

Hi. Is this a bug in git version 2.47.1? Or am I using it incorrectly?

# erase existing example.com credentials
printf "host=example.com\nprotocol=https\n" | git -c
credential.helper= -c credential.helper=cache credential reject
# store bearer token with expiry in far future in credential-cache
printf "host=example.com\nprotocol=https\nauthtype=bearer\ncredential=letmein\npassword_expiry_utc=2147483640\n"
| git credential-cache store
# try to retrieve credential
printf "host=example.com\nprotocol=https\n" | git -c
credential.helper= -c credential.helper=cache credential fill

Expected output (complete credential):

protocol=https
host=example.com
authtype=bearer
credential=letmein
password_expiry_utc=2147483640

Actual output (incomplete credential, no prompt for username or password):

protocol=https
host=example.com
password_expiry_utc=2147483640

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Fwd: [Bug] `credential fill` prints incomplete bearer credential
  2024-12-18 20:42 ` Fwd: [Bug] `credential fill` prints incomplete bearer credential M Hickford
@ 2024-12-19  2:02   ` brian m. carlson
  2024-12-19  5:56     ` Junio C Hamano
                       ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: brian m. carlson @ 2024-12-19  2:02 UTC (permalink / raw)
  To: M Hickford; +Cc: Git Mailing List

[-- Attachment #1: Type: text/plain, Size: 3098 bytes --]

On 2024-12-18 at 20:42:31, M Hickford wrote:
> Hi. Is this a bug in git version 2.47.1? Or am I using it incorrectly?
> 
> # erase existing example.com credentials
> printf "host=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential reject
> # store bearer token with expiry in far future in credential-cache
> printf "host=example.com\nprotocol=https\nauthtype=bearer\ncredential=letmein\npassword_expiry_utc=2147483640\n"
> | git credential-cache store
> # try to retrieve credential
> printf "host=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential fill
> 
> Expected output (complete credential):
> 
> protocol=https
> host=example.com
> authtype=bearer
> credential=letmein
> password_expiry_utc=2147483640
> 
> Actual output (incomplete credential, no prompt for username or password):
> 
> protocol=https
> host=example.com
> password_expiry_utc=2147483640

This is expected.  Every request to a credential helper should include
all of the capabilities that the caller supports on input, and the
credential helper will always emit those on output.  `git credential`,
however, will only emit the capabilities that were actually supported,
so that general callers (including Git LFS) can determine the actual
set of supported capabilities.

In this case, you asked the cache helper for a credential, but didn't
tell it that you supported `authtype` and `credential`.  Therefore, the
only safe thing it can assume is that you are incapable of parsing and
understanding those fields, so it doesn't emit them.  This is a benefit
for security, because some tooling logs all fields but the `password`
field, and we don't want to include new secret fields that the caller is
going to shovel into a file or syslog.

In addition, the helper could actually store two different sets of
credentials, one which is a username and password, and one which is an
authtype and credential.  If you provided the capability, the latter
would be omitted, but otherwise the former would.  That can be helpful
if you have a stronger credential type but might occasionally need to
use older software (say, older versions of Git or Git LFS).

However, if you provide the proper capability, this works as you expect:

----
% printf "host=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential reject
% printf "capability[]=authtype\nhost=example.com\nprotocol=https\nauthtype=bearer\ncredential=letmein\npassword_expiry_utc=2147483640\n" | git credential-cache store
% printf "capability[]=authtype\nhost=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential fill
capability[]=authtype
authtype=bearer
credential=letmein
protocol=https
host=example.com
password_expiry_utc=2147483640
----

Note that `capability[]` directives should always start the request to
allow one-pass parsing.

Hopefully this is helpful.
-- 
brian m. carlson (they/them or he/him)
Toronto, Ontario, CA

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Fwd: [Bug] `credential fill` prints incomplete bearer credential
  2024-12-19  2:02   ` brian m. carlson
@ 2024-12-19  5:56     ` Junio C Hamano
  2024-12-19 19:12     ` M Hickford
  2024-12-19 19:15     ` M Hickford
  2 siblings, 0 replies; 6+ messages in thread
From: Junio C Hamano @ 2024-12-19  5:56 UTC (permalink / raw)
  To: brian m. carlson; +Cc: M Hickford, Git Mailing List

"brian m. carlson" <sandals@crustytoothpaste.net> writes:

> On 2024-12-18 at 20:42:31, M Hickford wrote:
>> Hi. Is this a bug in git version 2.47.1? Or am I using it incorrectly?
>> 
>> # erase existing example.com credentials
>> printf "host=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential reject
>> # store bearer token with expiry in far future in credential-cache
>> printf "host=example.com\nprotocol=https\nauthtype=bearer\ncredential=letmein\npassword_expiry_utc=2147483640\n"
>> | git credential-cache store
>> # try to retrieve credential
>> printf "host=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential fill
>> 
>> Expected output (complete credential):
>> 
>> protocol=https
>> host=example.com
>> authtype=bearer
>> credential=letmein
>> password_expiry_utc=2147483640
>> 
>> Actual output (incomplete credential, no prompt for username or password):
>> 
>> protocol=https
>> host=example.com
>> password_expiry_utc=2147483640
>
> This is expected.  Every request to a credential helper should include
> all of the capabilities that the caller supports on input, and the
> credential helper will always emit those on output.  `git credential`,
> however, will only emit the capabilities that were actually supported,
> so that general callers (including Git LFS) can determine the actual
> set of supported capabilities.
> ...

The original report did

 - run "git credential reject" to clear
 - run "git credential-cache store"!!
 - run "git credential fill" to check

which looked curious.

Am I correct to understand that if the second step is replaced with
"git credential approve" (which calls "credential-cache store"
internally), the right thing happens and necessary capabilities are
passed?

Thanks.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Fwd: [Bug] `credential fill` prints incomplete bearer credential
  2024-12-19  2:02   ` brian m. carlson
  2024-12-19  5:56     ` Junio C Hamano
@ 2024-12-19 19:12     ` M Hickford
  2024-12-19 19:15     ` M Hickford
  2 siblings, 0 replies; 6+ messages in thread
From: M Hickford @ 2024-12-19 19:12 UTC (permalink / raw)
  To: brian m. carlson, M Hickford, Git Mailing List

On Thu, 19 Dec 2024 at 02:02, brian m. carlson
<sandals@crustytoothpaste.net> wrote:
>
> On 2024-12-18 at 20:42:31, M Hickford wrote:
> > Hi. Is this a bug in git version 2.47.1? Or am I using it incorrectly?
> >
> > # erase existing example.com credentials
> > printf "host=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential reject
> > # store bearer token with expiry in far future in credential-cache
> > printf "host=example.com\nprotocol=https\nauthtype=bearer\ncredential=letmein\npassword_expiry_utc=2147483640\n"
> > | git credential-cache store
> > # try to retrieve credential
> > printf "host=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential fill
> >
> > Expected output (complete credential):
> >
> > protocol=https
> > host=example.com
> > authtype=bearer
> > credential=letmein
> > password_expiry_utc=2147483640
> >
> > Actual output (incomplete credential, no prompt for username or password):
> >
> > protocol=https
> > host=example.com
> > password_expiry_utc=2147483640
>
> This is expected.  Every request to a credential helper should include
> all of the capabilities that the caller supports on input, and the
> credential helper will always emit those on output.  `git credential`,
> however, will only emit the capabilities that were actually supported,
> so that general callers (including Git LFS) can determine the actual
> set of supported capabilities.
>
> In this case, you asked the cache helper for a credential, but didn't
> tell it that you supported `authtype` and `credential`.  Therefore, the
> only safe thing it can assume is that you are incapable of parsing and
> understanding those fields, so it doesn't emit them.  This is a benefit
> for security, because some tooling logs all fields but the `password`
> field, and we don't want to include new secret fields that the caller is
> going to shovel into a file or syslog.

Thank you Brian for the explanation. That fits my example.

Typically `credential fill` prompts the user if it can't complete a
credential. Surely it should prompt in this case too?

https://git-scm.com/docs/git-credential "git-credential will attempt
to add "username" and "password" attributes to the description by
reading config files, by contacting any configured credential helpers,
or by prompting the user"

>
> In addition, the helper could actually store two different sets of
> credentials, one which is a username and password, and one which is an
> authtype and credential.  If you provided the capability, the latter
> would be omitted, but otherwise the former would.  That can be helpful
> if you have a stronger credential type but might occasionally need to
> use older software (say, older versions of Git or Git LFS).
>
> However, if you provide the proper capability, this works as you expect:
>
> ----
> % printf "host=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential reject
> % printf "capability[]=authtype\nhost=example.com\nprotocol=https\nauthtype=bearer\ncredential=letmein\npassword_expiry_utc=2147483640\n" | git credential-cache store
> % printf "capability[]=authtype\nhost=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential fill
> capability[]=authtype
> authtype=bearer
> credential=letmein
> protocol=https
> host=example.com
> password_expiry_utc=2147483640
> ----
>
> Note that `capability[]` directives should always start the request to
> allow one-pass parsing.
>
> Hopefully this is helpful.
> --
> brian m. carlson (they/them or he/him)
> Toronto, Ontario, CA

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Fwd: [Bug] `credential fill` prints incomplete bearer credential
  2024-12-19  2:02   ` brian m. carlson
  2024-12-19  5:56     ` Junio C Hamano
  2024-12-19 19:12     ` M Hickford
@ 2024-12-19 19:15     ` M Hickford
  2024-12-21  8:08       ` M Hickford
  2 siblings, 1 reply; 6+ messages in thread
From: M Hickford @ 2024-12-19 19:15 UTC (permalink / raw)
  To: brian m. carlson, M Hickford, Git Mailing List

On Thu, 19 Dec 2024 at 02:02, brian m. carlson
<sandals@crustytoothpaste.net> wrote:
>
> On 2024-12-18 at 20:42:31, M Hickford wrote:
> > Hi. Is this a bug in git version 2.47.1? Or am I using it incorrectly?
> >
> > # erase existing example.com credentials
> > printf "host=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential reject
> > # store bearer token with expiry in far future in credential-cache
> > printf "host=example.com\nprotocol=https\nauthtype=bearer\ncredential=letmein\npassword_expiry_utc=2147483640\n"
> > | git credential-cache store
> > # try to retrieve credential
> > printf "host=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential fill
> >
> > Expected output (complete credential):
> >
> > protocol=https
> > host=example.com
> > authtype=bearer
> > credential=letmein
> > password_expiry_utc=2147483640
> >
> > Actual output (incomplete credential, no prompt for username or password):
> >
> > protocol=https
> > host=example.com
> > password_expiry_utc=2147483640
>
> This is expected.  Every request to a credential helper should include
> all of the capabilities that the caller supports on input, and the
> credential helper will always emit those on output.  `git credential`,
> however, will only emit the capabilities that were actually supported,
> so that general callers (including Git LFS) can determine the actual
> set of supported capabilities.
>
> In this case, you asked the cache helper for a credential, but didn't
> tell it that you supported `authtype` and `credential`.  Therefore, the
> only safe thing it can assume is that you are incapable of parsing and
> understanding those fields, so it doesn't emit them.  This is a benefit
> for security, because some tooling logs all fields but the `password`
> field, and we don't want to include new secret fields that the caller is
> going to shovel into a file or syslog.
>
> In addition, the helper could actually store two different sets of
> credentials, one which is a username and password, and one which is an
> authtype and credential.  If you provided the capability, the latter
> would be omitted, but otherwise the former would.  That can be helpful
> if you have a stronger credential type but might occasionally need to
> use older software (say, older versions of Git or Git LFS).
>
> However, if you provide the proper capability, this works as you expect:
>
> ----
> % printf "host=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential reject
> % printf "capability[]=authtype\nhost=example.com\nprotocol=https\nauthtype=bearer\ncredential=letmein\npassword_expiry_utc=2147483640\n" | git credential-cache store
> % printf "capability[]=authtype\nhost=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential fill
> capability[]=authtype
> authtype=bearer
> credential=letmein
> protocol=https
> host=example.com
> password_expiry_utc=2147483640
> ----
>
> Note that `capability[]` directives should always start the request to
> allow one-pass parsing.

I think a bug exists in credential-cache. Below it receives a query
*without* capability authtype, upgrades it *with* capability authtype
and prints a bearer credential.

git credential-cache exit
# store bearer credential
printf "capability[]=authtype\nhost=example.com\nprotocol=https\nauthtype=bearer\ncredential=letmein\npassword_expiry_utc=2147483640\n"
| git credential-cache store
# query with capability authtype (prints bearer credential as expected)
printf "capability[]=authtype\nhost=example.com\nprotocol=https\n" |
git credential-cache get
# query without capability authtype (expect nothing)
printf "host=example.com\nprotocol=https\n" | git credential-cache get

If you agree that this is a bug, we could add a test case to
helper_test_authtype.

Here's a second simpler example of credential-cache of upgrading a request:

git credential-cache exit
# store credential
printf "host=example.com\nprotocol=https\nusername=tim\npassword=hunter2\n"
| git credential-cache store
# get credential (response is upgraded with capability authtype)
printf "host=example.com\nprotocol=https" | git credential-cache get



>
> Hopefully this is helpful.
> --
> brian m. carlson (they/them or he/him)
> Toronto, Ontario, CA

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Fwd: [Bug] `credential fill` prints incomplete bearer credential
  2024-12-19 19:15     ` M Hickford
@ 2024-12-21  8:08       ` M Hickford
  0 siblings, 0 replies; 6+ messages in thread
From: M Hickford @ 2024-12-21  8:08 UTC (permalink / raw)
  To: M Hickford; +Cc: brian m. carlson, Git Mailing List

On Thu, 19 Dec 2024 at 19:15, M Hickford <mirth.hickford@gmail.com> wrote:
>
> On Thu, 19 Dec 2024 at 02:02, brian m. carlson
> <sandals@crustytoothpaste.net> wrote:
> >
> > On 2024-12-18 at 20:42:31, M Hickford wrote:
> > > Hi. Is this a bug in git version 2.47.1? Or am I using it incorrectly?
> > >
> > > # erase existing example.com credentials
> > > printf "host=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential reject
> > > # store bearer token with expiry in far future in credential-cache
> > > printf "host=example.com\nprotocol=https\nauthtype=bearer\ncredential=letmein\npassword_expiry_utc=2147483640\n"
> > > | git credential-cache store
> > > # try to retrieve credential
> > > printf "host=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential fill
> > >
> > > Expected output (complete credential):
> > >
> > > protocol=https
> > > host=example.com
> > > authtype=bearer
> > > credential=letmein
> > > password_expiry_utc=2147483640
> > >
> > > Actual output (incomplete credential, no prompt for username or password):
> > >
> > > protocol=https
> > > host=example.com
> > > password_expiry_utc=2147483640
> >
> > This is expected.  Every request to a credential helper should include
> > all of the capabilities that the caller supports on input, and the
> > credential helper will always emit those on output.  `git credential`,
> > however, will only emit the capabilities that were actually supported,
> > so that general callers (including Git LFS) can determine the actual
> > set of supported capabilities.
> >
> > In this case, you asked the cache helper for a credential, but didn't
> > tell it that you supported `authtype` and `credential`.  Therefore, the
> > only safe thing it can assume is that you are incapable of parsing and
> > understanding those fields, so it doesn't emit them.  This is a benefit
> > for security, because some tooling logs all fields but the `password`
> > field, and we don't want to include new secret fields that the caller is
> > going to shovel into a file or syslog.
> >
> > In addition, the helper could actually store two different sets of
> > credentials, one which is a username and password, and one which is an
> > authtype and credential.  If you provided the capability, the latter
> > would be omitted, but otherwise the former would.  That can be helpful
> > if you have a stronger credential type but might occasionally need to
> > use older software (say, older versions of Git or Git LFS).
> >
> > However, if you provide the proper capability, this works as you expect:
> >
> > ----
> > % printf "host=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential reject
> > % printf "capability[]=authtype\nhost=example.com\nprotocol=https\nauthtype=bearer\ncredential=letmein\npassword_expiry_utc=2147483640\n" | git credential-cache store
> > % printf "capability[]=authtype\nhost=example.com\nprotocol=https\n" | git -c credential.helper= -c credential.helper=cache credential fill
> > capability[]=authtype
> > authtype=bearer
> > credential=letmein
> > protocol=https
> > host=example.com
> > password_expiry_utc=2147483640
> > ----
> >
> > Note that `capability[]` directives should always start the request to
> > allow one-pass parsing.
>
> I think a bug exists in credential-cache. Below it receives a query
> *without* capability authtype, upgrades it *with* capability authtype
> and prints a bearer credential.
>
> git credential-cache exit
> # store bearer credential
> printf "capability[]=authtype\nhost=example.com\nprotocol=https\nauthtype=bearer\ncredential=letmein\npassword_expiry_utc=2147483640\n"
> | git credential-cache store
> # query with capability authtype (prints bearer credential as expected)
> printf "capability[]=authtype\nhost=example.com\nprotocol=https\n" |
> git credential-cache get
> # query without capability authtype (expect nothing)
> printf "host=example.com\nprotocol=https\n" | git credential-cache get
>
> If you agree that this is a bug, we could add a test case to
> helper_test_authtype.

Here's a small fix and test for credential-cache
https://lore.kernel.org/git/pull.1842.git.1734729534213.gitgitgadget@gmail.com/

>
> Here's a second simpler example of credential-cache of upgrading a request:
>
> git credential-cache exit
> # store credential
> printf "host=example.com\nprotocol=https\nusername=tim\npassword=hunter2\n"
> | git credential-cache store
> # get credential (response is upgraded with capability authtype)
> printf "host=example.com\nprotocol=https" | git credential-cache get
>
>
>
> >
> > Hopefully this is helpful.
> > --
> > brian m. carlson (they/them or he/him)
> > Toronto, Ontario, CA

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2024-12-21  8:09 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <CAGJzqs=ksKqY2M8Px3uv6ut=MBwkmpPUqp3xVzVpNMJ0YBrBww@mail.gmail.com>
2024-12-18 20:42 ` Fwd: [Bug] `credential fill` prints incomplete bearer credential M Hickford
2024-12-19  2:02   ` brian m. carlson
2024-12-19  5:56     ` Junio C Hamano
2024-12-19 19:12     ` M Hickford
2024-12-19 19:15     ` M Hickford
2024-12-21  8:08       ` M Hickford

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).