Re: git-tag bug? confusing git fast-export with double tag objects

3 messages, 3 authors, 2016-06-15 · open the first message on its own page

Re: git-tag bug? confusing git fast-export with double tag objects

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:46:47

Andreas Ericsson [off-list ref] writes:
You re-create all your tag refs with same-name tags that point to the
old tags.
Joe Dev fetches from you, but your tags do not get stored as refs.
Joe Dev publishes a repo somewhere with a bunch of topic-branches and
requests you merge from those repositories.
You fetch from Joe.

Now we have two opposite problems.
If tags aren't updated when Joe Dev fetches from you, his refs will
not match yours when you fetch from him, and anyone cloning from him
even after the re-sign will never get the new tags at all.
If tag refs *do* get updated when fetching from a repo when we already
have another tag ref with the same name, you fetching from Joe Dev
could undo all your re-created tags and make the new tag-objects
garbage-collectable. This assumes Joe Dev published his repo before
fetching your new tags though.

Perhaps I'm missing something....
No, you did not miss anything.  It illustrates the problem space very
well.

There are two "names" to a tag.  The name of a tag is recorded in the
object itself, in its "tag" header.

        $ git cat-file tag v1.6.3
        object f01f1099f40f24fe6f7802185340a6fa3a3d4f35
        type commit
        tag v1.6.3
        tagger Junio C Hamano [off-list ref] 1241659007 -0700

        GIT 1.6.3
        -----BEGIN PGP SIGNATURE-----
        Version: GnuPG v1.4.9 (GNU/Linux)
        ...

Anybody can forge, even down to the trailing signature part with a
compromised key, such a tag object that claims to be "tag v1.6.3" and
point anything with it.

But the "name" you usually access a tag object with is not this one.
Instead, you use the name of the ref in refs/tags hierarchy.  These two
names are supposed to match by convention, and I think recent fsck even
checks it.

Unlike the name recorded in tag objects, you can have only one v1.6.3 in
your ref namespace.  And the way git protects users from maliciously made
tags has been by not re-fetching what already exist unless explicitly
asked.  The consequence of this is that you somehow obtained a forged or
vulnerable one first, you will not get corrected ones automatically.

But that is a feature in the current set-up.

If the key that signs release tags were compromised and the tags got
re-signed with a new key (whether I re-tag by pointing at the commit
objects, or pointing at the old-genuine tag objects), that fact needs to
be advertised ("Sorry, but I had to re-tag; if you have old tags, please
re-fetch"), and the user who is currently protected by this "no automatic
re-fetching" mechanism has to somehow assert that "Sorry" is really from
me, and allow git to re-fetch.

The workflow for a such case would be:

 (0) I notice the signing key was somehow compromised; roll a new key,
     re-sign the tags, and send out a "I had to re-tag, and here is a list
     of the old and new tag object names you can use to verify" message;

 (1) You read such a message,  You do "git for-each-ref refs/tags" to see
     the object names to check with my message, and realize that you have
     stale tags.  So does Joe Dev but he may be slower to react;

 (2) You fetch (or ls-remote) from Joe Dev which is your preferrerd mirror
     of my tree and notice he hasn't updated, and let him know.  In the
     meantime you fetch "git fetch --tags" from me, and verify the result
     against my message.

 (3) Joe Dev would do the same.

That's largely manual, cumbersome, and makes everybody involved painfully
aware of what is going on, which may be an advantage over silently
updating with a new tag without telling anybody.

But you can improve the situation without losing security by doing
something like this.

 * Introduce a concept of "trusted signing keys" (similar to the way
   distros sign their binary packages), whose fingerprints are probably
   stored in .git/config of the receiving repositories;

 * Upon 'git tag -v <name>', verify that the signature was made with one
   of the trusted signing keys;

 * Inside 'git fetch':

   - before starting to fetch, see if there are signed tags that exist
     locally but not signed with any of the trusted keys;

   - for the signed tags we find in the above step, if the remote end has
     different tag object at the same refname, ask for them;

   - perform the main 'git fetch' transfer and store things according to
     the refspec as usual (but do not store the tags re-fetched only
     because of the new logic yet);

   - for the tags re-fetched with the new logic, see if they are signed by
     trusted keys, and if so replace the stale tags with them.

The step (0) to issue a "Sorry but I had to re-tag" message with "here is
the fingerprint of new signing key" is still necessary, and you need to
react to it by replacing the old trusted signing key with the fingerprint
of the new key, but after that everything can be made automatic.

Re: git-tag bug? confusing git fast-export with double tag objects

From: Matthias Andree <hidden>
Date: 2016-06-15 22:46:47

Am 16.05.2009, 19:16 Uhr, schrieb Junio C Hamano [off-list ref]:

The workflow for a such case would be:

 (0) I notice the signing key was somehow compromised; roll a new key,
     re-sign the tags, and send out a "I had to re-tag, and here is a  
list
     of the old and new tag object names you can use to verify" message;

 (1) You read such a message,  You do "git for-each-ref refs/tags" to see
     the object names to check with my message, and realize that you have
     stale tags.  So does Joe Dev but he may be slower to react;

 (2) You fetch (or ls-remote) from Joe Dev which is your preferrerd  
mirror
     of my tree and notice he hasn't updated, and let him know.  In the
     meantime you fetch "git fetch --tags" from me, and verify the result
     against my message.

 (3) Joe Dev would do the same.

That's largely manual, cumbersome, and makes everybody involved painfully
aware of what is going on, which may be an advantage over silently
updating with a new tag without telling anybody.

But you can improve the situation without losing security by doing
something like this.
Let's do things step by step and fix the current issue - and I fear there  
won't be an easy technical solution, so let's amend to the documentation  
for the nonce.

OK, what I was trying to do is rewrite history to fix up some b0rked  
internal addresses. That's a repository for a mostly frozen project, which  
is more a reference point than a basis for development. I had to recreate  
the few tag signatures they were, and hence I used "git tag -f" without  
thinking too much. I had seen the section on re-tagging, and am aware of  
it, but it somehow didn't apply to my situation.

I think we ought

(1) to fix the git tag -h output and manual page for consistency, and

(2) to add a note to make users aware that they can also tag tags (the  
[<object>] in SYNOPSIS may not be hint enough, as Git seems to differ  
substantially from other SCM systems in this respect - so this is a  
usability concern that deserves documentation).

I'll suggest something, but that can take a couple of days.

What else can we tag in Git? Commits and Tags.  Is it sensible and does it  
work to tag blobs or trees?

-- 
Matthias Andree

Re: git-tag bug? confusing git fast-export with double tag objects

From: Jeff King <hidden>
Date: 2016-06-15 22:46:47

On Tue, May 19, 2009 at 01:21:58PM +0200, Matthias Andree wrote:
What else can we tag in Git? Commits and Tags.  Is it sensible and does it 
work to tag blobs or trees?
A tagged blob:

  $ cd git && git show junio-gpg-pub | sed '/^--/Q'
  tag junio-gpg-pub
  Tagger: Junio C Hamano [off-list ref]
  Date:   Tue Dec 13 16:33:29 2005 -0800


  GPG key to sign git.git archive.

  This blob object contains the GPG public key I use to sign git.git
  archive.

  To use it to verify tags I signed, do:

    $ git-cat-file blob junio-gpg-pub | gpg --import

  to import it into your keyring, and then

    $ git-verify-tag $tag_to_be_verified

A tagged tree:

  $ cd linux-2.6 && git show v2.6.11 | sed '/^--/Q'
  tag v2.6.11-tree

  This is the 2.6.11 tree object.

  NOTE! There's no commit for this, since it happened before I started with git.
  Eventually we'll import some sort of history, and that should tie this tree
  object up to a real commit. In the meantime, this acts as an anchor point for
  doing diffs etc under git.

-Peff
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help