git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* git tag -v should verify that the tag signer intended the same tag name as the user is verifying
@ 2019-03-20 12:24 Daniel Kahn Gillmor
  2019-03-20 14:20 ` Santiago Torres Arias
                   ` (2 more replies)
  0 siblings, 3 replies; 15+ messages in thread
From: Daniel Kahn Gillmor @ 2019-03-20 12:24 UTC (permalink / raw)
  To: git

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

Hi git folks--

I understand that git tags can be easily renamed.  for example:

    git tag push origin refs/tags/v0.0.3:refs/tags/v2.3.4

However, for tags signed with any recent version of git, the tag name is
also included in the signed material:

    0 dkg@test:~$ git tag -v v0.0.3
    object 8ae6a246bef5b5eb0684e9fc1c933a4f8441dadd
    type commit
    tag v0.0.3
    tagger Daniel Kahn Gillmor <dkg@fifthhorseman.net> 1528706225 +0200

    this is my tag message
    gpg: Signature made Mon 11 Jun 2018 04:37:05 AM EDT
    gpg:                using Ed25519 key C90E6D36200A1B922A1509E77618196529AE5FF8
    gpg: Good signature from "Daniel Kahn Gillmor <dkg@fifthhorseman.net>" [ultimate]
    Primary key fingerprint: C4BC 2DDB 38CC E964 85EB  E9C2 F206 9117 9038 E5C6
    0 dkg@test:~$

But git tag doesn't verify that the internal name is the same as the
external name (note that it still returns an exit code of zero):

    0 dkg@test:~$ git tag -v v2.3.4
    object 8ae6a246bef5b5eb0684e9fc1c933a4f8441dadd
    type commit
    tag v0.0.3
    tagger Daniel Kahn Gillmor <dkg@fifthhorseman.net> 1528706225 +0200

    this is my tag message
    gpg: Signature made Mon 11 Jun 2018 04:37:05 AM EDT
    gpg:                using Ed25519 key C90E6D36200A1B922A1509E77618196529AE5FF8
    gpg: Good signature from "Daniel Kahn Gillmor <dkg@fifthhorseman.net>" [ultimate]
    Primary key fingerprint: C4BC 2DDB 38CC E964 85EB  E9C2 F206 9117 9038 E5C6
    0 dkg@test:~$

This seems troublesome, as I expect there are many scripts that rely on
the tag name and the return code of "git tag -v" to assert that this is
a correct tag.  Anyone in control of the above repository could pass off
an old tag (or indeed, a tag from an entirely different project that
happens to be signed by the same author) as whatever version they wanted
to, and convince automated scripts that work with new versions to
"upgrade".

I think "git tag -v" should be more strict about what it needs to "pass"
a verification.

At a minimum, if the internal tag name (the line matching "^tag " before
the first blank line) doesn't match the tag name being verified, "git
tag -v" should report a warning to stderr and return a non-zero error
code.

What do you think?

i'm not subscribed to git@vger.kernel.org, so please keep me in Cc on
this thread, thanks!

    --dkg

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

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

* Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying
  2019-03-20 12:24 git tag -v should verify that the tag signer intended the same tag name as the user is verifying Daniel Kahn Gillmor
@ 2019-03-20 14:20 ` Santiago Torres Arias
  2019-03-20 22:00   ` Daniel Kahn Gillmor
  2019-03-20 22:35 ` Ævar Arnfjörð Bjarmason
  2019-03-21  1:21 ` Junio C Hamano
  2 siblings, 1 reply; 15+ messages in thread
From: Santiago Torres Arias @ 2019-03-20 14:20 UTC (permalink / raw)
  To: Daniel Kahn Gillmor; +Cc: git

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

Hi,

This has been known for a whlie now[1]. The consensus back then was that
this information was up to higher-level integrators to verify using
means like e.g., --format.

This is implemented in for example pacman/devtools here[2]. We published
a paper with a more thorough security model here[3], and there's some
stalled work into implementing this using push certificates...

Thanks,
-Santiago.

[1] https://public-inbox.org/git/xmqqk2hzldx8.fsf@gitster.mtv.corp.google.com/
[2] https://lists.archlinux.org/pipermail/pacman-dev/2017-September/022123.html
[3] https://www.usenix.org/conference/usenixsecurity16/technical-sessions/presentation/torres-arias

On Wed, Mar 20, 2019 at 08:24:46AM -0400, Daniel Kahn Gillmor wrote:
> Hi git folks--
> 
> I understand that git tags can be easily renamed.  for example:
> 
>     git tag push origin refs/tags/v0.0.3:refs/tags/v2.3.4
> 
> However, for tags signed with any recent version of git, the tag name is
> also included in the signed material:
> 
>     0 dkg@test:~$ git tag -v v0.0.3
>     object 8ae6a246bef5b5eb0684e9fc1c933a4f8441dadd
>     type commit
>     tag v0.0.3
>     tagger Daniel Kahn Gillmor <dkg@fifthhorseman.net> 1528706225 +0200
> 
>     this is my tag message
>     gpg: Signature made Mon 11 Jun 2018 04:37:05 AM EDT
>     gpg:                using Ed25519 key C90E6D36200A1B922A1509E77618196529AE5FF8
>     gpg: Good signature from "Daniel Kahn Gillmor <dkg@fifthhorseman.net>" [ultimate]
>     Primary key fingerprint: C4BC 2DDB 38CC E964 85EB  E9C2 F206 9117 9038 E5C6
>     0 dkg@test:~$
> 
> But git tag doesn't verify that the internal name is the same as the
> external name (note that it still returns an exit code of zero):
> 
>     0 dkg@test:~$ git tag -v v2.3.4
>     object 8ae6a246bef5b5eb0684e9fc1c933a4f8441dadd
>     type commit
>     tag v0.0.3
>     tagger Daniel Kahn Gillmor <dkg@fifthhorseman.net> 1528706225 +0200
> 
>     this is my tag message
>     gpg: Signature made Mon 11 Jun 2018 04:37:05 AM EDT
>     gpg:                using Ed25519 key C90E6D36200A1B922A1509E77618196529AE5FF8
>     gpg: Good signature from "Daniel Kahn Gillmor <dkg@fifthhorseman.net>" [ultimate]
>     Primary key fingerprint: C4BC 2DDB 38CC E964 85EB  E9C2 F206 9117 9038 E5C6
>     0 dkg@test:~$
> 
> This seems troublesome, as I expect there are many scripts that rely on
> the tag name and the return code of "git tag -v" to assert that this is
> a correct tag.  Anyone in control of the above repository could pass off
> an old tag (or indeed, a tag from an entirely different project that
> happens to be signed by the same author) as whatever version they wanted
> to, and convince automated scripts that work with new versions to
> "upgrade".
> 
> I think "git tag -v" should be more strict about what it needs to "pass"
> a verification.
> 
> At a minimum, if the internal tag name (the line matching "^tag " before
> the first blank line) doesn't match the tag name being verified, "git
> tag -v" should report a warning to stderr and return a non-zero error
> code.
> 
> What do you think?
> 
> i'm not subscribed to git@vger.kernel.org, so please keep me in Cc on
> this thread, thanks!
> 
>     --dkg



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

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

* Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying
  2019-03-20 14:20 ` Santiago Torres Arias
@ 2019-03-20 22:00   ` Daniel Kahn Gillmor
  0 siblings, 0 replies; 15+ messages in thread
From: Daniel Kahn Gillmor @ 2019-03-20 22:00 UTC (permalink / raw)
  To: Santiago Torres Arias; +Cc: git

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

Hi Santiago--

On Wed 2019-03-20 10:20:57 -0400, Santiago Torres Arias wrote:
> This has been known for a whlie now[1]. The consensus back then was that
> this information was up to higher-level integrators to verify using
> means like e.g., --format.
>
> [1] https://public-inbox.org/git/xmqqk2hzldx8.fsf@gitster.mtv.corp.google.com/

Thanks for this pointer to the history!  Glad to see people have pushed
on it in the past, even if i don't think the place that conversation
wound down to is the right place to settle.

> This is implemented in for example pacman/devtools here[2].
>
> [2] https://lists.archlinux.org/pipermail/pacman-dev/2017-September/022123.html

Sigh.  This is exactly the kind of redundant implementation situation
that i'm afraid of getting into.  as the comment in that patch says:

    This really should be fixed in git itself, rather than forcing all
    downstream users of git verify-tag to implement their own checks,

Git gets to decide what choices to make here about what the default
verification process is, and the default verification step should be
sensible and narrowly aligned to the standard case associated with
revision control tag verification.

gpg and gpgv can both be used to confirm the validity of the signature,
but those tools don't (and architecturally can't) know that they're
being used in the context of git -- so it's important that git supplies
that domain-specific knowledge to the verification step.

fwiw, i'm pushing for comparable checks in the git-buildpackage

   https://bugs.debian.org/925118

but it seems pretty silly (and likely error-prone) to have to rewrite
the same check in every tool that uses "git tag -v".

> We published a paper with a more thorough security model here[3], and
> there's some stalled work into implementing this using push
> certificates...
>
> [3] https://www.usenix.org/conference/usenixsecurity16/technical-sessions/presentation/torres-arias

I'm not convinced that push certificates solves this problem, if i'm
understanding the work right.  push certificates have to do specifically
with the ability to push to a repository, but here we're talking about
arbitrary verifiers who have passive (read-only) access to a repository
wanting to verify a given tag.

If you're talking about using a push certificate as a substitute for a
signed tag itself, then that sounds like we're giving up on signed tags
meaning what everyone expects them to mean, all because we can't get the
verification process to work right.  That doesn't seem like a good
outcome.

Thanks for talking through this -- hopefully we can figure out a good
way forward.

       --dkg

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

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

* Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying
  2019-03-20 12:24 git tag -v should verify that the tag signer intended the same tag name as the user is verifying Daniel Kahn Gillmor
  2019-03-20 14:20 ` Santiago Torres Arias
@ 2019-03-20 22:35 ` Ævar Arnfjörð Bjarmason
  2019-03-22  4:00   ` Daniel Kahn Gillmor
  2019-03-21  1:21 ` Junio C Hamano
  2 siblings, 1 reply; 15+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2019-03-20 22:35 UTC (permalink / raw)
  To: Daniel Kahn Gillmor; +Cc: git, Santiago Torres


On Wed, Mar 20 2019, Daniel Kahn Gillmor wrote:

> Hi git folks--
>
> I understand that git tags can be easily renamed.  for example:
>
>     git tag push origin refs/tags/v0.0.3:refs/tags/v2.3.4
>
> However, for tags signed with any recent version of git, the tag name is
> also included in the signed material:
>
>     0 dkg@test:~$ git tag -v v0.0.3
>     object 8ae6a246bef5b5eb0684e9fc1c933a4f8441dadd
>     type commit
>     tag v0.0.3
>     tagger Daniel Kahn Gillmor <dkg@fifthhorseman.net> 1528706225 +0200
>
>     this is my tag message
>     gpg: Signature made Mon 11 Jun 2018 04:37:05 AM EDT
>     gpg:                using Ed25519 key C90E6D36200A1B922A1509E77618196529AE5FF8
>     gpg: Good signature from "Daniel Kahn Gillmor <dkg@fifthhorseman.net>" [ultimate]
>     Primary key fingerprint: C4BC 2DDB 38CC E964 85EB  E9C2 F206 9117 9038 E5C6
>     0 dkg@test:~$
>
> But git tag doesn't verify that the internal name is the same as the
> external name (note that it still returns an exit code of zero):
>
>     0 dkg@test:~$ git tag -v v2.3.4
>     object 8ae6a246bef5b5eb0684e9fc1c933a4f8441dadd
>     type commit
>     tag v0.0.3
>     tagger Daniel Kahn Gillmor <dkg@fifthhorseman.net> 1528706225 +0200
>
>     this is my tag message
>     gpg: Signature made Mon 11 Jun 2018 04:37:05 AM EDT
>     gpg:                using Ed25519 key C90E6D36200A1B922A1509E77618196529AE5FF8
>     gpg: Good signature from "Daniel Kahn Gillmor <dkg@fifthhorseman.net>" [ultimate]
>     Primary key fingerprint: C4BC 2DDB 38CC E964 85EB  E9C2 F206 9117 9038 E5C6
>     0 dkg@test:~$

I'm sympathetic to the whole problem, but don't have anything to add to
t he thread Santiago linked to. Except...

> This seems troublesome, as I expect there are many scripts that rely on
> the tag name and the return code of "git tag -v" to assert that this is
> a correct tag.  Anyone in control of the above repository could pass off
> an old tag (or indeed, a tag from an entirely different project that
> happens to be signed by the same author) as whatever version they wanted
> to, and convince automated scripts that work with new versions to
> "upgrade".
>
> I think "git tag -v" should be more strict about what it needs to "pass"
> a verification.

... just a point of clarification on the "a tag from an entirely
different project" part of this.

Maybe I'm missing something, but it doesn't seem like your proposed
solution helps much with *that* threat model as you've described it.

If all I'm doing is blindly slurping down one out of a bunch of
repositories you commit to and tag releases in, sorting the tags, and
getting the latest one you (dkg@fifthhorseman.net) signed, I'm still
mostly open to this problem.

The only thing that'll change is that you can't fool me if I'm looking
at whatever project you happen to contribute to that has the highest tag
version across *all* projects you contribute to.

But e.g. if you've signed a v1.00 in foo.git, but also maintain bar.git
and have a v2.00 there, I can be fooled in foo.git with your proposed
change by having the v2.00 bar.git tag pushed to it (just, with the
proposed change, not the other way around).

It *does* help with the "pass of an old tag [from the same repository]"
problem, which I'd expect would realistically be the only threat model
that matters (forcing a downgrade to an old buggy version), whereas some
entirely different project is likely going to be next fed to some
project-specific build infrastructure and then won't even build.

*but*

I wonder if there's a more general fix to be found here that'll have
nothing to do with GPG or signed tags per-se. A lot of people have this
"given tags in the repo, what's the latest one?" problem. I think
they'll mostly use the --sort option now, maybe some variant of that
which for each <older>/<newer> tag in the chain also checked:

    git merge-base --is-ancestor <older> <newer>

That would serve as a check for such rouge tags, even if none of them
were signed, and a "they must be signed" option could be added, along
with "start walking from here".

It wouldn't help with cases where you legitimately *do* want to re-tag
an old version (for a revert), but in some cases tagging always moves
forward in history (always newer commits).

Just food for thought...

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

* Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying
  2019-03-20 12:24 git tag -v should verify that the tag signer intended the same tag name as the user is verifying Daniel Kahn Gillmor
  2019-03-20 14:20 ` Santiago Torres Arias
  2019-03-20 22:35 ` Ævar Arnfjörð Bjarmason
@ 2019-03-21  1:21 ` Junio C Hamano
  2019-03-21  1:31   ` Junio C Hamano
  2 siblings, 1 reply; 15+ messages in thread
From: Junio C Hamano @ 2019-03-21  1:21 UTC (permalink / raw)
  To: Daniel Kahn Gillmor; +Cc: git

Daniel Kahn Gillmor <dkg@fifthhorseman.net> writes:

> I understand that git tags can be easily renamed.  for example:
>
>     git tag push origin refs/tags/v0.0.3:refs/tags/v2.3.4
>
> However, for tags signed with any recent version of git, the tag name is
> also included in the signed material:
> ...
> But git tag doesn't verify that the internal name is the same as the
> external name (note that it still returns an exit code of zero):

That is all very much deliberate.  A few additional things you may
want to consider while assessing the proposal in your message are:

 * "git tag -v $(git rev-parse v1.0.0)" should work, but the command
   would not even see which ref the 40-hex object name it is
   verifying came from.  As "tag --verify" is about verifying the
   crypto signature over the data in the tag object, the lack of the
   information (and verification) is perfectly fine when "tag -v"
   does not begin with a refname but works from an object name. 

   I.e. your proposal to additionally check the refname of a signed
   tag must be made optional, something like "only when a refname is
   given, teach 'tag -v' to additionally check that the refname
   matches the tagname".

 * There are movements to push tags you obtain from upstream to a
   somewhere not directly underneath refs/tags/.  Instead of your
   artificial "confuse users by calling 2.3.4 what in reality is a
   mere 0.0.3" example, what would more likely to happen in the real
   world is "we see v2.3.4 at the upstream repository; copy it at
   refs/tags/origin/v2.3.4 in our repository".  If you literally
   followed your proposal, your users will be hit with "You told me
   to verify origin/v2.3.4 but the data in the tag itself claims
   that it is v2.3.4 without 'origin/' prefix--this is an error".

   Perhaps checking only the tail-match is good enough?  It is when
   you consider only this example, but that is merely one example
   and is far from exhaustive.  Your proposal needs to be fine tuned
   after thinking these details through.

 * "git describe" knows that the path under refs/tags/ and the
   tagname could be different, so after you rename v2.20.0 to
   g2.20.0, you would see something like this:

   $ git checkout --detach v2.20.0
   $ git update-ref refs/tags/g2.20.0 refs/tags/v2.20.0
   $ git update-ref -d refs/tags/v2.20.0
   $ git describe
   warning: tag 'v2.20.0' is really 'g2.20.0' here
   v2.20.0

   in today's Git already.  Porting this warning logic (which is a
   dumb one that reports any non-exact match) to "tag -v" might be
   sufficient, as long as you do not make it an error.

We may want to teach "git fsck" to notice discrepancy between the
tagname and the refname, but the same care needs to be taken to
allow sensible renaming as the second point above.

Thanks.

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

* Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying
  2019-03-21  1:21 ` Junio C Hamano
@ 2019-03-21  1:31   ` Junio C Hamano
  2019-03-21 11:43     ` Ævar Arnfjörð Bjarmason
  2019-03-22  5:19     ` Daniel Kahn Gillmor
  0 siblings, 2 replies; 15+ messages in thread
From: Junio C Hamano @ 2019-03-21  1:31 UTC (permalink / raw)
  To: Daniel Kahn Gillmor; +Cc: git

Junio C Hamano <gitster@pobox.com> writes:

>  * "git tag -v $(git rev-parse v1.0.0)" should work, but the command

Sorry, forget about this part of my message.  I completely forgot the
discussion we had a few years ago:

https://public-inbox.org/git/CAPc5daV9ZvHqFtdzr565vp6Mv7O66ySr-p5Vi8o6bd6=GyVELg@mail.gmail.com/

In short, "git tag -v TAGNAME" does not take an arbitrary object
name, TAGNAME does not go through the usual ref dwimming rules
(i.e. checking for .git/%s, .git/tag/%s, .git/heads/%s, ... to find
one) but only looks at refs/tags/TAGNAME alone.  So we always have
the refname it came from when inspecting tag contents that tells
what tagname the tag has.

The other point still stands; there are legitimate reasons people
would want to have a tag with v1.0.0 tagname in somewhere that is
not refs/tags/v1.0.0 and an extra validation must need to make sure
it won't error out, even though warning is probably acceptable.

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

* Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying
  2019-03-21  1:31   ` Junio C Hamano
@ 2019-03-21 11:43     ` Ævar Arnfjörð Bjarmason
  2019-03-22  5:19     ` Daniel Kahn Gillmor
  1 sibling, 0 replies; 15+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2019-03-21 11:43 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Daniel Kahn Gillmor, git


On Thu, Mar 21 2019, Junio C Hamano wrote:

> Junio C Hamano <gitster@pobox.com> writes:
>
>>  * "git tag -v $(git rev-parse v1.0.0)" should work, but the command
>
> Sorry, forget about this part of my message.  I completely forgot the
> discussion we had a few years ago:
>
> https://public-inbox.org/git/CAPc5daV9ZvHqFtdzr565vp6Mv7O66ySr-p5Vi8o6bd6=GyVELg@mail.gmail.com/
>
> In short, "git tag -v TAGNAME" does not take an arbitrary object
> name, TAGNAME does not go through the usual ref dwimming rules
> (i.e. checking for .git/%s, .git/tag/%s, .git/heads/%s, ... to find
> one) but only looks at refs/tags/TAGNAME alone.  So we always have
> the refname it came from when inspecting tag contents that tells
> what tagname the tag has.
>
> The other point still stands; there are legitimate reasons people
> would want to have a tag with v1.0.0 tagname in somewhere that is
> not refs/tags/v1.0.0 and an extra validation must need to make sure
> it won't error out, even though warning is probably acceptable.

One such example, which I don't know is actually used, but we might be
careful to break is:

 * Someone (e.g. Junio) is producing signed tags of a project like
   git.git

 * Someone else has a git repo where only upstream (signed by Junio)
   releases are allowed, but they decide *which* release.

 * Some system auto-deploys whatever the latest sorted tag in that repo
   is, after verifying that Junio tagged them.

Thus e.g. v2.21.0 might be pushed as refs/tags/2018-03-21, and if it
doesn't work out a new refs/tags/2018-03-22 might be tagged tomorrow
using the v2.20.0 tag.

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

* Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying
  2019-03-20 22:35 ` Ævar Arnfjörð Bjarmason
@ 2019-03-22  4:00   ` Daniel Kahn Gillmor
  2019-03-24 14:55     ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 15+ messages in thread
From: Daniel Kahn Gillmor @ 2019-03-22  4:00 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason; +Cc: git, Santiago Torres

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

On Wed 2019-03-20 23:35:48 +0100, Ævar Arnfjörð Bjarmason wrote:
> But e.g. if you've signed a v1.00 in foo.git, but also maintain bar.git
> and have a v2.00 there, I can be fooled in foo.git with your proposed
> change by having the v2.00 bar.git tag pushed to it (just, with the
> proposed change, not the other way around).

Presumably the tool looking for the "most interesting new tag" already
has some sort of pattern that it looks for in a tag name (to avoid
accidentally ingesting some development-specific, non-release tag).

So yes, this is true for upstreams which issue signed release tags on
multiple projects named with the generic form v1.2.3, but it is *not*
true of projects which name their tags the way that (for example)
GnuPG's upstream does (e.g. gnupg-2.2.14 and libgpg-error-1.36).

In that case, and the matching pattern itself will exclude tags from
other repositories.

> It *does* help with the "pass of an old tag [from the same repository]"
> problem, which I'd expect would realistically be the only threat model
> that matters (forcing a downgrade to an old buggy version), whereas some
> entirely different project is likely going to be next fed to some
> project-specific build infrastructure and then won't even build.

I agree that a cross-project tag substitution attack is more exotic than
an in-project downgrade or freeze attack, but i'm not inclined to wager
on it never being exploitable.  Why take that gamble?

> I wonder if there's a more general fix to be found here that'll have
> nothing to do with GPG or signed tags per-se. A lot of people have this
> "given tags in the repo, what's the latest one?" problem. I think
> they'll mostly use the --sort option now, maybe some variant of that
> which for each <older>/<newer> tag in the chain also checked:
>
>     git merge-base --is-ancestor <older> <newer>
>
> That would serve as a check for such rouge tags, even if none of them
> were signed, and a "they must be signed" option could be added, along
> with "start walking from here".

I agree that this is a common tag verification use case, and i've seen
probably a dozen different attempts to do it which all fail in some
curious ways if you assume that the repository being pulled from is
malicious.

I like the idea you're describing here, and would be happy to see some
reasonable, easy-to-use git subcommand that says something like "find
the most interesting tag that derives from the current HEAD".  for some
version of "interesting", of course :) It would probably be a good start
to have "interesting" mean:

 * the tag name matches some particular pattern
 
 * the tag is cryptographically signed by at least one member of a
   specific curated keyring
   
 * the tag is the "most recent" or "farthest descendant" (these are
   subtly different, i'm not sure which one makes more sense)

Anyway, the fact that there isn't an obvious perfect answer for how to
do this shouldn't stop git from offering a reasonable, well-vetted,
*good* answer.  Because the current situation just means that every
project that cares about verifying signed tags makes up their own
approach, and i would happily bet that most of them get it wrong in some
corner case.

And if there's a tool that does a sensible verification of some workflow
that we think is reasonable, that tool will also help to encourgae
projects to adopt that reasonable workflow.  This is a good thing!

       --dkg

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

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

* Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying
  2019-03-21  1:31   ` Junio C Hamano
  2019-03-21 11:43     ` Ævar Arnfjörð Bjarmason
@ 2019-03-22  5:19     ` Daniel Kahn Gillmor
  2019-03-24 12:26       ` Junio C Hamano
  1 sibling, 1 reply; 15+ messages in thread
From: Daniel Kahn Gillmor @ 2019-03-22  5:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Thanks for the thoughtful feedback, Junio!

On Thu 2019-03-21 10:31:59 +0900, Junio C Hamano wrote:
> The other point still stands; there are legitimate reasons people
> would want to have a tag with v1.0.0 tagname in somewhere that is
> not refs/tags/v1.0.0 and an extra validation must need to make sure
> it won't error out, even though warning is probably acceptable.

It would be great if "git tag -v" would present a warning by default in
case of a tag name mismatch!  I would not want to rule out making it
possible to return an error though.

I don't personally have any use case for doing such a tag rename -- you
mention two:

 a) wanting to call tag "foo" that you found on remote "origin" by the
    name of "origin/foo"

 b) wanting to call "v2.20.0" by the name "g2.20.0"

And Ævar mentions a third:

 c) mapping versioned tags (e.g. "v2.20.0") to tags with a date name
    ("2018-03-22")

I'm not sure how realistic or useful any of these patterns are.  While
(a) seems the most plausible of the lot to me, none of them are things
i've ever seen in practice.

So i'd say that anyone in such a scenario is the outlier, and i wouldn't
want the existence of that edge case to make git less useful in the much
more common case.

Here's a revised proposal:

Consider a config setting named tag.verifyNameMatch, which can be true,
false, or some sort of sed expression name mangler.

 - If set to true, it would do the thing that naive users probably
   expect when they do "git tag -v foo" -- show a warning *and* return
   an error if the tag message itself doesn't have "tag foo" in the
   "header section" of the signed tag.

 - If set to false, it wouldn't error out (though maybe it would still
   show the warning).

 - If set to a sed expression, it would feed the name being checked
   through the sed expression and ensure that the resultant value was
   present in the signed tag's "header section".

The mangler would work in a pretty straightforward way for (a)
(e.g. "s_origin/(.*)_\1_") and (b) (e.g. "s_v(.*)_g\1_").

i don't see how it would handle (c), but i think there are probably
better ways to handle (c) (if i'm understanding Ævar's scenario
correctly) than just trying to replay the upstream author's tags with
different names.  For example, the curator of the repository could just
make their own signed tags, based on whatever policy they wanted.  Or,
they could just ignore the warnings :P

As you can probably guess, i'd say that such a tag.verifyNameMatch
should default to true, but i'd also be ok if it started off defaulting
to false, to gather feedback about its impact, and eventually consider
transitioning it to true by default.

      --dkg

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

* Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying
  2019-03-22  5:19     ` Daniel Kahn Gillmor
@ 2019-03-24 12:26       ` Junio C Hamano
  2019-03-24 15:07         ` Daniel Kahn Gillmor
  0 siblings, 1 reply; 15+ messages in thread
From: Junio C Hamano @ 2019-03-24 12:26 UTC (permalink / raw)
  To: Daniel Kahn Gillmor; +Cc: git

Daniel Kahn Gillmor <dkg@fifthhorseman.net> writes:

> I don't personally have any use case for doing such a tag rename -- you
> mention two:
>
>  a) wanting to call tag "foo" that you found on remote "origin" by the
>     name of "origin/foo"
>
>  b) wanting to call "v2.20.0" by the name "g2.20.0"

For the record, in the latter there is no "wanting to call".  It was
merely a set-up used to illustrate what support there already exists
in the current system that helps making users aware of tags that are
not stored in there "natural" place.

The former however is a natural consequence of noises people make
around here from time to time, wanting to have tags you grab from
elsewhere and tags you create locally in separate places.

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

* Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying
  2019-03-22  4:00   ` Daniel Kahn Gillmor
@ 2019-03-24 14:55     ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 15+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2019-03-24 14:55 UTC (permalink / raw)
  To: Daniel Kahn Gillmor; +Cc: git, Santiago Torres


On Fri, Mar 22 2019, Daniel Kahn Gillmor wrote:

> On Wed 2019-03-20 23:35:48 +0100, Ævar Arnfjörð Bjarmason wrote:
>> But e.g. if you've signed a v1.00 in foo.git, but also maintain bar.git
>> and have a v2.00 there, I can be fooled in foo.git with your proposed
>> change by having the v2.00 bar.git tag pushed to it (just, with the
>> proposed change, not the other way around).
>
> Presumably the tool looking for the "most interesting new tag" already
> has some sort of pattern that it looks for in a tag name (to avoid
> accidentally ingesting some development-specific, non-release tag).
>
> So yes, this is true for upstreams which issue signed release tags on
> multiple projects named with the generic form v1.2.3, but it is *not*
> true of projects which name their tags the way that (for example)
> GnuPG's upstream does (e.g. gnupg-2.2.14 and libgpg-error-1.36).
>
> In that case, and the matching pattern itself will exclude tags from
> other repositories.
>
>> It *does* help with the "pass of an old tag [from the same repository]"
>> problem, which I'd expect would realistically be the only threat model
>> that matters (forcing a downgrade to an old buggy version), whereas some
>> entirely different project is likely going to be next fed to some
>> project-specific build infrastructure and then won't even build.
>
> I agree that a cross-project tag substitution attack is more exotic than
> an in-project downgrade or freeze attack, but i'm not inclined to wager
> on it never being exploitable.  Why take that gamble?

FWIW I wasn't arguing that this was a good thing ("just a point of
clarification..."), just walking through and elaborating an exploitable
case you mentioned so we're all on the same page as to what the current
problem(s) are.

>> I wonder if there's a more general fix to be found here that'll have
>> nothing to do with GPG or signed tags per-se. A lot of people have this
>> "given tags in the repo, what's the latest one?" problem. I think
>> they'll mostly use the --sort option now, maybe some variant of that
>> which for each <older>/<newer> tag in the chain also checked:
>>
>>     git merge-base --is-ancestor <older> <newer>
>>
>> That would serve as a check for such rouge tags, even if none of them
>> were signed, and a "they must be signed" option could be added, along
>> with "start walking from here".
>
> I agree that this is a common tag verification use case, and i've seen
> probably a dozen different attempts to do it which all fail in some
> curious ways if you assume that the repository being pulled from is
> malicious.
>
> I like the idea you're describing here, and would be happy to see some
> reasonable, easy-to-use git subcommand that says something like "find
> the most interesting tag that derives from the current HEAD".  for some
> version of "interesting", of course :) It would probably be a good start
> to have "interesting" mean:
>
>  * the tag name matches some particular pattern
>
>  * the tag is cryptographically signed by at least one member of a
>    specific curated keyring
>
>  * the tag is the "most recent" or "farthest descendant" (these are
>    subtly different, i'm not sure which one makes more sense)
>
> Anyway, the fact that there isn't an obvious perfect answer for how to
> do this shouldn't stop git from offering a reasonable, well-vetted,
> *good* answer.  Because the current situation just means that every
> project that cares about verifying signed tags makes up their own
> approach, and i would happily bet that most of them get it wrong in some
> corner case.
>
> And if there's a tool that does a sensible verification of some workflow
> that we think is reasonable, that tool will also help to encourgae
> projects to adopt that reasonable workflow.  This is a good thing!
>
>        --dkg

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

* Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying
  2019-03-24 12:26       ` Junio C Hamano
@ 2019-03-24 15:07         ` Daniel Kahn Gillmor
  2019-03-25  2:27           ` Junio C Hamano
  0 siblings, 1 reply; 15+ messages in thread
From: Daniel Kahn Gillmor @ 2019-03-24 15:07 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On Sun 2019-03-24 21:26:13 +0900, Junio C Hamano wrote:
> Daniel Kahn Gillmor <dkg@fifthhorseman.net> writes:
>
>> I don't personally have any use case for doing such a tag rename -- you
>> mention two:
>>
>>  a) wanting to call tag "foo" that you found on remote "origin" by the
>>     name of "origin/foo"
>>
>>  b) wanting to call "v2.20.0" by the name "g2.20.0"
>
> For the record, in the latter there is no "wanting to call".  It was
> merely a set-up used to illustrate what support there already exists
> in the current system that helps making users aware of tags that are
> not stored in there "natural" place.
>
> The former however is a natural consequence of noises people make
> around here from time to time, wanting to have tags you grab from
> elsewhere and tags you create locally in separate places.

Gotcha, thanks.  I like the warnings that are already showing up from
(b) So I won't worry about (b) as a justification then, but rather keep
my focus on (a).  (and i still think that (c) has better solutions than
tag renaming)

What do you think of my updated proposal for tag.verifyNameMatch ?

     --dkg

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

* Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying
  2019-03-24 15:07         ` Daniel Kahn Gillmor
@ 2019-03-25  2:27           ` Junio C Hamano
  2019-03-26 17:35             ` Daniel Kahn Gillmor
  0 siblings, 1 reply; 15+ messages in thread
From: Junio C Hamano @ 2019-03-25  2:27 UTC (permalink / raw)
  To: Daniel Kahn Gillmor; +Cc: git

Daniel Kahn Gillmor <dkg@fifthhorseman.net> writes:


> What do you think of my updated proposal for tag.verifyNameMatch ?

Meh to slightly negative for hard-coding project-specific preference
to the core tools.  "We give you --format so go wild in your project
to do verification your project likes." I think was the conclusion of
the previous round of discussions, and I do not think we saw any new
arguments in this round to rethink it in a different way.



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

* Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying
  2019-03-25  2:27           ` Junio C Hamano
@ 2019-03-26 17:35             ` Daniel Kahn Gillmor
  2019-03-26 18:40               ` Jeff King
  0 siblings, 1 reply; 15+ messages in thread
From: Daniel Kahn Gillmor @ 2019-03-26 17:35 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

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

On Mon 2019-03-25 11:27:06 +0900, Junio C Hamano wrote:
> Daniel Kahn Gillmor <dkg@fifthhorseman.net> writes:
>
>> What do you think of my updated proposal for tag.verifyNameMatch ?
>
> Meh to slightly negative for hard-coding project-specific preference
> to the core tools.  "We give you --format so go wild in your project
> to do verification your project likes." I think was the conclusion of
> the previous round of discussions, and I do not think we saw any new
> arguments in this round to rethink it in a different way.

Hm, maybe --format is all that's necessary to resolve the concerns about
errors affecting scenario (a) ?  If that's the case, then maybe the path
forward is a warning on tagname mismatch (and maybe i can convince you
later than an actual error could be acceptable :P)

But I don't see how to use --format with "git tag -v" at all.  Can you
show me what i'm doing wrong?  git-tag(1) says that --format defaults to
'%(refname:strip=2)', but git tag -v behaves differently when i specify
that same default explicitly:

    0 dkg@alice:~/src/pkg-gnupg/gnupg2$ git tag -v gnupg-2.2.13
    object 7922e2dd1c7eee48a8a2cf4799827942489ddd0f
    type commit
    tag gnupg-2.2.13
    tagger Werner Koch <wk@gnupg.org> 1549985965 +0100

    You may want to watch the Ellsberg/Chomsky discussion
    at <https://riseuptimes.org/2018/04/25/daniel-ellsberg-and-noam-chomsky-discuss-nuclear-war/>
    or at <https://theintercept.com/chomsky-ellsberg/>
    gpg: Signature made Tue 12 Feb 2019 04:41:32 PM CET
    gpg:                using RSA key D8692123C4065DEA5E0F3AB5249B39D24F25E3B6
    gpg: Good signature from "Werner Koch (dist sig)" [full]
    Primary key fingerprint: D869 2123 C406 5DEA 5E0F  3AB5 249B 39D2 4F25 E3B6
    0 dkg@alice:~/src/pkg-gnupg/gnupg2$ git tag -v --format='%(refname:strip=2)' gnupg-2.2.13

    0 dkg@alice:~/src/pkg-gnupg/gnupg2$ 

What am i missing?

     --dkg

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

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

* Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying
  2019-03-26 17:35             ` Daniel Kahn Gillmor
@ 2019-03-26 18:40               ` Jeff King
  0 siblings, 0 replies; 15+ messages in thread
From: Jeff King @ 2019-03-26 18:40 UTC (permalink / raw)
  To: Daniel Kahn Gillmor; +Cc: Junio C Hamano, git

On Tue, Mar 26, 2019 at 06:35:57PM +0100, Daniel Kahn Gillmor wrote:

> But I don't see how to use --format with "git tag -v" at all.  Can you
> show me what i'm doing wrong?  git-tag(1) says that --format defaults to
> '%(refname:strip=2)', but git tag -v behaves differently when i specify
> that same default explicitly:

Hmm.

I think the documentation is unclear. For a normal listing of tags,
the default format is the stripped refname, and you can override it with
--format.

For "-v", the default is to dump the whole tag contents (i.e.,
traditionally it just ran "verify-tag -v" under the hood, though I think
it is all done internally now).

So this doesn't surprise me:

>     0 dkg@alice:~/src/pkg-gnupg/gnupg2$ git tag -v gnupg-2.2.13
>     object 7922e2dd1c7eee48a8a2cf4799827942489ddd0f
>     type commit
>     tag gnupg-2.2.13
>     tagger Werner Koch <wk@gnupg.org> 1549985965 +0100
> 
>     You may want to watch the Ellsberg/Chomsky discussion
>     at <https://riseuptimes.org/2018/04/25/daniel-ellsberg-and-noam-chomsky-discuss-nuclear-war/>
>     or at <https://theintercept.com/chomsky-ellsberg/>
>     gpg: Signature made Tue 12 Feb 2019 04:41:32 PM CET
>     gpg:                using RSA key D8692123C4065DEA5E0F3AB5249B39D24F25E3B6
>     gpg: Good signature from "Werner Koch (dist sig)" [full]
>     Primary key fingerprint: D869 2123 C406 5DEA 5E0F  3AB5 249B 39D2 4F25 E3B6

But this does:

>     0 dkg@alice:~/src/pkg-gnupg/gnupg2$ git tag -v --format='%(refname:strip=2)' gnupg-2.2.13

I'd expect it to print the tagname here. It looks like we only feed the
partial tagname to the ref-formatting machinery, so the "strip" doesn't
do what you'd expect.

It also doesn't show the gpg output, though it does actually verify the
tag. But AFAIK there's no format specifier in the ref-filter language
for showing the GPG output! What a mess.

-Peff

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

end of thread, other threads:[~2019-03-26 18:40 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-20 12:24 git tag -v should verify that the tag signer intended the same tag name as the user is verifying Daniel Kahn Gillmor
2019-03-20 14:20 ` Santiago Torres Arias
2019-03-20 22:00   ` Daniel Kahn Gillmor
2019-03-20 22:35 ` Ævar Arnfjörð Bjarmason
2019-03-22  4:00   ` Daniel Kahn Gillmor
2019-03-24 14:55     ` Ævar Arnfjörð Bjarmason
2019-03-21  1:21 ` Junio C Hamano
2019-03-21  1:31   ` Junio C Hamano
2019-03-21 11:43     ` Ævar Arnfjörð Bjarmason
2019-03-22  5:19     ` Daniel Kahn Gillmor
2019-03-24 12:26       ` Junio C Hamano
2019-03-24 15:07         ` Daniel Kahn Gillmor
2019-03-25  2:27           ` Junio C Hamano
2019-03-26 17:35             ` Daniel Kahn Gillmor
2019-03-26 18:40               ` Jeff King

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).