Andreas Ericsson <ae@xxxxxx> 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 <gitster@xxxxxxxxx> 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. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html