{"thread":{"id":"50791","subject":"git tag -v should verify that the tag signer intended the same tag name as the user is verifying","startedAt":"2019-03-20T12:33:31Z","lastAt":"2019-03-26T18:40:05Z","messageCount":15,"participants":["Daniel Kahn Gillmor","Santiago Torres Arias","Ævar Arnfjörð Bjarmason","Junio C Hamano","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"372004","messageId":"875zsdu41d.fsf@fifthhorseman.net","threadId":"50791","inReplyTo":null,"subject":"git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Daniel Kahn Gillmor","fromEmail":"dkg@fifthhorseman.net","sentAt":"2019-03-20T12:24:46Z","receivedAt":"2019-03-20T12:33:31Z","isPatch":false,"sender":{"key":"dkg@fifthhorseman.net","avatar":null},"body":"Hi git folks--\n\nI understand that git tags can be easily renamed.  for example:\n\n    git tag push origin refs/tags/v0.0.3:refs/tags/v2.3.4\n\nHowever, for tags signed with any recent version of git, the tag name is\nalso included in the signed material:\n\n    0 dkg@test:~$ git tag -v v0.0.3\n    object 8ae6a246bef5b5eb0684e9fc1c933a4f8441dadd\n    type commit\n    tag v0.0.3\n    tagger Daniel Kahn Gillmor <dkg@fifthhorseman.net> 1528706225 +0200\n\n    this is my tag message\n    gpg: Signature made Mon 11 Jun 2018 04:37:05 AM EDT\n    gpg:                using Ed25519 key C90E6D36200A1B922A1509E77618196529AE5FF8\n    gpg: Good signature from \"Daniel Kahn Gillmor <dkg@fifthhorseman.net>\" [ultimate]\n    Primary key fingerprint: C4BC 2DDB 38CC E964 85EB  E9C2 F206 9117 9038 E5C6\n    0 dkg@test:~$\n\nBut git tag doesn't verify that the internal name is the same as the\nexternal name (note that it still returns an exit code of zero):\n\n    0 dkg@test:~$ git tag -v v2.3.4\n    object 8ae6a246bef5b5eb0684e9fc1c933a4f8441dadd\n    type commit\n    tag v0.0.3\n    tagger Daniel Kahn Gillmor <dkg@fifthhorseman.net> 1528706225 +0200\n\n    this is my tag message\n    gpg: Signature made Mon 11 Jun 2018 04:37:05 AM EDT\n    gpg:                using Ed25519 key C90E6D36200A1B922A1509E77618196529AE5FF8\n    gpg: Good signature from \"Daniel Kahn Gillmor <dkg@fifthhorseman.net>\" [ultimate]\n    Primary key fingerprint: C4BC 2DDB 38CC E964 85EB  E9C2 F206 9117 9038 E5C6\n    0 dkg@test:~$\n\nThis seems troublesome, as I expect there are many scripts that rely on\nthe tag name and the return code of \"git tag -v\" to assert that this is\na correct tag.  Anyone in control of the above repository could pass off\nan old tag (or indeed, a tag from an entirely different project that\nhappens to be signed by the same author) as whatever version they wanted\nto, and convince automated scripts that work with new versions to\n\"upgrade\".\n\nI think \"git tag -v\" should be more strict about what it needs to \"pass\"\na verification.\n\nAt a minimum, if the internal tag name (the line matching \"^tag \" before\nthe first blank line) doesn't match the tag name being verified, \"git\ntag -v\" should report a warning to stderr and return a non-zero error\ncode.\n\nWhat do you think?\n\ni'm not subscribed to git@vger.kernel.org, so please keep me in Cc on\nthis thread, thanks!\n\n    --dkg\n"},{"id":"372007","messageId":"20190320142055.zlh5iby5pxs3fy3r@LykOS.localdomain","threadId":"50791","inReplyTo":"875zsdu41d.fsf@fifthhorseman.net","subject":"Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Santiago Torres Arias","fromEmail":"santiago@nyu.edu","sentAt":"2019-03-20T14:20:57Z","receivedAt":"2019-03-20T14:21:05Z","isPatch":false,"sender":{"key":"santiago@nyu.edu","avatar":"https://avatars.githubusercontent.com/u/3579933?v=4"},"body":"Hi,\n\nThis has been known for a whlie now[1]. The consensus back then was that\nthis information was up to higher-level integrators to verify using\nmeans like e.g., --format.\n\nThis is implemented in for example pacman/devtools here[2]. We published\na paper with a more thorough security model here[3], and there's some\nstalled work into implementing this using push certificates...\n\nThanks,\n-Santiago.\n\n[1] https://public-inbox.org/git/xmqqk2hzldx8.fsf@gitster.mtv.corp.google.com/\n[2] https://lists.archlinux.org/pipermail/pacman-dev/2017-September/022123.html\n[3] https://www.usenix.org/conference/usenixsecurity16/technical-sessions/presentation/torres-arias\n\nOn Wed, Mar 20, 2019 at 08:24:46AM -0400, Daniel Kahn Gillmor wrote:\n> Hi git folks--\n> \n> I understand that git tags can be easily renamed.  for example:\n> \n>     git tag push origin refs/tags/v0.0.3:refs/tags/v2.3.4\n> \n> However, for tags signed with any recent version of git, the tag name is\n> also included in the signed material:\n> \n>     0 dkg@test:~$ git tag -v v0.0.3\n>     object 8ae6a246bef5b5eb0684e9fc1c933a4f8441dadd\n>     type commit\n>     tag v0.0.3\n>     tagger Daniel Kahn Gillmor <dkg@fifthhorseman.net> 1528706225 +0200\n> \n>     this is my tag message\n>     gpg: Signature made Mon 11 Jun 2018 04:37:05 AM EDT\n>     gpg:                using Ed25519 key C90E6D36200A1B922A1509E77618196529AE5FF8\n>     gpg: Good signature from \"Daniel Kahn Gillmor <dkg@fifthhorseman.net>\" [ultimate]\n>     Primary key fingerprint: C4BC 2DDB 38CC E964 85EB  E9C2 F206 9117 9038 E5C6\n>     0 dkg@test:~$\n> \n> But git tag doesn't verify that the internal name is the same as the\n> external name (note that it still returns an exit code of zero):\n> \n>     0 dkg@test:~$ git tag -v v2.3.4\n>     object 8ae6a246bef5b5eb0684e9fc1c933a4f8441dadd\n>     type commit\n>     tag v0.0.3\n>     tagger Daniel Kahn Gillmor <dkg@fifthhorseman.net> 1528706225 +0200\n> \n>     this is my tag message\n>     gpg: Signature made Mon 11 Jun 2018 04:37:05 AM EDT\n>     gpg:                using Ed25519 key C90E6D36200A1B922A1509E77618196529AE5FF8\n>     gpg: Good signature from \"Daniel Kahn Gillmor <dkg@fifthhorseman.net>\" [ultimate]\n>     Primary key fingerprint: C4BC 2DDB 38CC E964 85EB  E9C2 F206 9117 9038 E5C6\n>     0 dkg@test:~$\n> \n> This seems troublesome, as I expect there are many scripts that rely on\n> the tag name and the return code of \"git tag -v\" to assert that this is\n> a correct tag.  Anyone in control of the above repository could pass off\n> an old tag (or indeed, a tag from an entirely different project that\n> happens to be signed by the same author) as whatever version they wanted\n> to, and convince automated scripts that work with new versions to\n> \"upgrade\".\n> \n> I think \"git tag -v\" should be more strict about what it needs to \"pass\"\n> a verification.\n> \n> At a minimum, if the internal tag name (the line matching \"^tag \" before\n> the first blank line) doesn't match the tag name being verified, \"git\n> tag -v\" should report a warning to stderr and return a non-zero error\n> code.\n> \n> What do you think?\n> \n> i'm not subscribed to git@vger.kernel.org, so please keep me in Cc on\n> this thread, thanks!\n> \n>     --dkg\n\n\n"},{"id":"372027","messageId":"87bm25rytw.fsf@fifthhorseman.net","threadId":"50791","inReplyTo":"20190320142055.zlh5iby5pxs3fy3r@LykOS.localdomain","subject":"Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Daniel Kahn Gillmor","fromEmail":"dkg@fifthhorseman.net","sentAt":"2019-03-20T22:00:11Z","receivedAt":"2019-03-20T22:00:17Z","isPatch":false,"sender":{"key":"dkg@fifthhorseman.net","avatar":null},"body":"Hi Santiago--\n\nOn Wed 2019-03-20 10:20:57 -0400, Santiago Torres Arias wrote:\n> This has been known for a whlie now[1]. The consensus back then was that\n> this information was up to higher-level integrators to verify using\n> means like e.g., --format.\n>\n> [1] https://public-inbox.org/git/xmqqk2hzldx8.fsf@gitster.mtv.corp.google.com/\n\nThanks for this pointer to the history!  Glad to see people have pushed\non it in the past, even if i don't think the place that conversation\nwound down to is the right place to settle.\n\n> This is implemented in for example pacman/devtools here[2].\n>\n> [2] https://lists.archlinux.org/pipermail/pacman-dev/2017-September/022123.html\n\nSigh.  This is exactly the kind of redundant implementation situation\nthat i'm afraid of getting into.  as the comment in that patch says:\n\n    This really should be fixed in git itself, rather than forcing all\n    downstream users of git verify-tag to implement their own checks,\n\nGit gets to decide what choices to make here about what the default\nverification process is, and the default verification step should be\nsensible and narrowly aligned to the standard case associated with\nrevision control tag verification.\n\ngpg and gpgv can both be used to confirm the validity of the signature,\nbut those tools don't (and architecturally can't) know that they're\nbeing used in the context of git -- so it's important that git supplies\nthat domain-specific knowledge to the verification step.\n\nfwiw, i'm pushing for comparable checks in the git-buildpackage\n\n   https://bugs.debian.org/925118\n\nbut it seems pretty silly (and likely error-prone) to have to rewrite\nthe same check in every tool that uses \"git tag -v\".\n\n> We published a paper with a more thorough security model here[3], and\n> there's some stalled work into implementing this using push\n> certificates...\n>\n> [3] https://www.usenix.org/conference/usenixsecurity16/technical-sessions/presentation/torres-arias\n\nI'm not convinced that push certificates solves this problem, if i'm\nunderstanding the work right.  push certificates have to do specifically\nwith the ability to push to a repository, but here we're talking about\narbitrary verifiers who have passive (read-only) access to a repository\nwanting to verify a given tag.\n\nIf you're talking about using a push certificate as a substitute for a\nsigned tag itself, then that sounds like we're giving up on signed tags\nmeaning what everyone expects them to mean, all because we can't get the\nverification process to work right.  That doesn't seem like a good\noutcome.\n\nThanks for talking through this -- hopefully we can figure out a good\nway forward.\n\n       --dkg\n"},{"id":"372029","messageId":"8736nhdvi3.fsf@evledraar.gmail.com","threadId":"50791","inReplyTo":"875zsdu41d.fsf@fifthhorseman.net","subject":"Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2019-03-20T22:35:48Z","receivedAt":"2019-03-20T22:35:53Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Wed, Mar 20 2019, Daniel Kahn Gillmor wrote:\n\n> Hi git folks--\n>\n> I understand that git tags can be easily renamed.  for example:\n>\n>     git tag push origin refs/tags/v0.0.3:refs/tags/v2.3.4\n>\n> However, for tags signed with any recent version of git, the tag name is\n> also included in the signed material:\n>\n>     0 dkg@test:~$ git tag -v v0.0.3\n>     object 8ae6a246bef5b5eb0684e9fc1c933a4f8441dadd\n>     type commit\n>     tag v0.0.3\n>     tagger Daniel Kahn Gillmor <dkg@fifthhorseman.net> 1528706225 +0200\n>\n>     this is my tag message\n>     gpg: Signature made Mon 11 Jun 2018 04:37:05 AM EDT\n>     gpg:                using Ed25519 key C90E6D36200A1B922A1509E77618196529AE5FF8\n>     gpg: Good signature from \"Daniel Kahn Gillmor <dkg@fifthhorseman.net>\" [ultimate]\n>     Primary key fingerprint: C4BC 2DDB 38CC E964 85EB  E9C2 F206 9117 9038 E5C6\n>     0 dkg@test:~$\n>\n> But git tag doesn't verify that the internal name is the same as the\n> external name (note that it still returns an exit code of zero):\n>\n>     0 dkg@test:~$ git tag -v v2.3.4\n>     object 8ae6a246bef5b5eb0684e9fc1c933a4f8441dadd\n>     type commit\n>     tag v0.0.3\n>     tagger Daniel Kahn Gillmor <dkg@fifthhorseman.net> 1528706225 +0200\n>\n>     this is my tag message\n>     gpg: Signature made Mon 11 Jun 2018 04:37:05 AM EDT\n>     gpg:                using Ed25519 key C90E6D36200A1B922A1509E77618196529AE5FF8\n>     gpg: Good signature from \"Daniel Kahn Gillmor <dkg@fifthhorseman.net>\" [ultimate]\n>     Primary key fingerprint: C4BC 2DDB 38CC E964 85EB  E9C2 F206 9117 9038 E5C6\n>     0 dkg@test:~$\n\nI'm sympathetic to the whole problem, but don't have anything to add to\nt he thread Santiago linked to. Except...\n\n> This seems troublesome, as I expect there are many scripts that rely on\n> the tag name and the return code of \"git tag -v\" to assert that this is\n> a correct tag.  Anyone in control of the above repository could pass off\n> an old tag (or indeed, a tag from an entirely different project that\n> happens to be signed by the same author) as whatever version they wanted\n> to, and convince automated scripts that work with new versions to\n> \"upgrade\".\n>\n> I think \"git tag -v\" should be more strict about what it needs to \"pass\"\n> a verification.\n\n... just a point of clarification on the \"a tag from an entirely\ndifferent project\" part of this.\n\nMaybe I'm missing something, but it doesn't seem like your proposed\nsolution helps much with *that* threat model as you've described it.\n\nIf all I'm doing is blindly slurping down one out of a bunch of\nrepositories you commit to and tag releases in, sorting the tags, and\ngetting the latest one you (dkg@fifthhorseman.net) signed, I'm still\nmostly open to this problem.\n\nThe only thing that'll change is that you can't fool me if I'm looking\nat whatever project you happen to contribute to that has the highest tag\nversion across *all* projects you contribute to.\n\nBut e.g. if you've signed a v1.00 in foo.git, but also maintain bar.git\nand have a v2.00 there, I can be fooled in foo.git with your proposed\nchange by having the v2.00 bar.git tag pushed to it (just, with the\nproposed change, not the other way around).\n\nIt *does* help with the \"pass of an old tag [from the same repository]\"\nproblem, which I'd expect would realistically be the only threat model\nthat matters (forcing a downgrade to an old buggy version), whereas some\nentirely different project is likely going to be next fed to some\nproject-specific build infrastructure and then won't even build.\n\n*but*\n\nI wonder if there's a more general fix to be found here that'll have\nnothing to do with GPG or signed tags per-se. A lot of people have this\n\"given tags in the repo, what's the latest one?\" problem. I think\nthey'll mostly use the --sort option now, maybe some variant of that\nwhich for each <older>/<newer> tag in the chain also checked:\n\n    git merge-base --is-ancestor <older> <newer>\n\nThat would serve as a check for such rouge tags, even if none of them\nwere signed, and a \"they must be signed\" option could be added, along\nwith \"start walking from here\".\n\nIt wouldn't help with cases where you legitimately *do* want to re-tag\nan old version (for a revert), but in some cases tagging always moves\nforward in history (always newer commits).\n\nJust food for thought...\n"},{"id":"372044","messageId":"xmqq5zsduinf.fsf@gitster-ct.c.googlers.com","threadId":"50791","inReplyTo":"875zsdu41d.fsf@fifthhorseman.net","subject":"Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-03-21T01:21:24Z","receivedAt":"2019-03-21T01:21:31Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Daniel Kahn Gillmor <dkg@fifthhorseman.net> writes:\n\n> I understand that git tags can be easily renamed.  for example:\n>\n>     git tag push origin refs/tags/v0.0.3:refs/tags/v2.3.4\n>\n> However, for tags signed with any recent version of git, the tag name is\n> also included in the signed material:\n> ...\n> But git tag doesn't verify that the internal name is the same as the\n> external name (note that it still returns an exit code of zero):\n\nThat is all very much deliberate.  A few additional things you may\nwant to consider while assessing the proposal in your message are:\n\n * \"git tag -v $(git rev-parse v1.0.0)\" should work, but the command\n   would not even see which ref the 40-hex object name it is\n   verifying came from.  As \"tag --verify\" is about verifying the\n   crypto signature over the data in the tag object, the lack of the\n   information (and verification) is perfectly fine when \"tag -v\"\n   does not begin with a refname but works from an object name. \n\n   I.e. your proposal to additionally check the refname of a signed\n   tag must be made optional, something like \"only when a refname is\n   given, teach 'tag -v' to additionally check that the refname\n   matches the tagname\".\n\n * There are movements to push tags you obtain from upstream to a\n   somewhere not directly underneath refs/tags/.  Instead of your\n   artificial \"confuse users by calling 2.3.4 what in reality is a\n   mere 0.0.3\" example, what would more likely to happen in the real\n   world is \"we see v2.3.4 at the upstream repository; copy it at\n   refs/tags/origin/v2.3.4 in our repository\".  If you literally\n   followed your proposal, your users will be hit with \"You told me\n   to verify origin/v2.3.4 but the data in the tag itself claims\n   that it is v2.3.4 without 'origin/' prefix--this is an error\".\n\n   Perhaps checking only the tail-match is good enough?  It is when\n   you consider only this example, but that is merely one example\n   and is far from exhaustive.  Your proposal needs to be fine tuned\n   after thinking these details through.\n\n * \"git describe\" knows that the path under refs/tags/ and the\n   tagname could be different, so after you rename v2.20.0 to\n   g2.20.0, you would see something like this:\n\n   $ git checkout --detach v2.20.0\n   $ git update-ref refs/tags/g2.20.0 refs/tags/v2.20.0\n   $ git update-ref -d refs/tags/v2.20.0\n   $ git describe\n   warning: tag 'v2.20.0' is really 'g2.20.0' here\n   v2.20.0\n\n   in today's Git already.  Porting this warning logic (which is a\n   dumb one that reports any non-exact match) to \"tag -v\" might be\n   sufficient, as long as you do not make it an error.\n\nWe may want to teach \"git fsck\" to notice discrepancy between the\ntagname and the refname, but the same care needs to be taken to\nallow sensible renaming as the second point above.\n\nThanks.\n"},{"id":"372045","messageId":"xmqq1s31ui5s.fsf@gitster-ct.c.googlers.com","threadId":"50791","inReplyTo":"xmqq5zsduinf.fsf@gitster-ct.c.googlers.com","subject":"Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-03-21T01:31:59Z","receivedAt":"2019-03-21T01:32:04Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n>  * \"git tag -v $(git rev-parse v1.0.0)\" should work, but the command\n\nSorry, forget about this part of my message.  I completely forgot the\ndiscussion we had a few years ago:\n\nhttps://public-inbox.org/git/CAPc5daV9ZvHqFtdzr565vp6Mv7O66ySr-p5Vi8o6bd6=GyVELg@mail.gmail.com/\n\nIn short, \"git tag -v TAGNAME\" does not take an arbitrary object\nname, TAGNAME does not go through the usual ref dwimming rules\n(i.e. checking for .git/%s, .git/tag/%s, .git/heads/%s, ... to find\none) but only looks at refs/tags/TAGNAME alone.  So we always have\nthe refname it came from when inspecting tag contents that tells\nwhat tagname the tag has.\n\nThe other point still stands; there are legitimate reasons people\nwould want to have a tag with v1.0.0 tagname in somewhere that is\nnot refs/tags/v1.0.0 and an extra validation must need to make sure\nit won't error out, even though warning is probably acceptable.\n"},{"id":"372090","messageId":"87r2b0cv1q.fsf@evledraar.gmail.com","threadId":"50791","inReplyTo":"xmqq1s31ui5s.fsf@gitster-ct.c.googlers.com","subject":"Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2019-03-21T11:43:13Z","receivedAt":"2019-03-21T11:43:19Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Thu, Mar 21 2019, Junio C Hamano wrote:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>>  * \"git tag -v $(git rev-parse v1.0.0)\" should work, but the command\n>\n> Sorry, forget about this part of my message.  I completely forgot the\n> discussion we had a few years ago:\n>\n> https://public-inbox.org/git/CAPc5daV9ZvHqFtdzr565vp6Mv7O66ySr-p5Vi8o6bd6=GyVELg@mail.gmail.com/\n>\n> In short, \"git tag -v TAGNAME\" does not take an arbitrary object\n> name, TAGNAME does not go through the usual ref dwimming rules\n> (i.e. checking for .git/%s, .git/tag/%s, .git/heads/%s, ... to find\n> one) but only looks at refs/tags/TAGNAME alone.  So we always have\n> the refname it came from when inspecting tag contents that tells\n> what tagname the tag has.\n>\n> The other point still stands; there are legitimate reasons people\n> would want to have a tag with v1.0.0 tagname in somewhere that is\n> not refs/tags/v1.0.0 and an extra validation must need to make sure\n> it won't error out, even though warning is probably acceptable.\n\nOne such example, which I don't know is actually used, but we might be\ncareful to break is:\n\n * Someone (e.g. Junio) is producing signed tags of a project like\n   git.git\n\n * Someone else has a git repo where only upstream (signed by Junio)\n   releases are allowed, but they decide *which* release.\n\n * Some system auto-deploys whatever the latest sorted tag in that repo\n   is, after verifying that Junio tagged them.\n\nThus e.g. v2.21.0 might be pushed as refs/tags/2018-03-21, and if it\ndoesn't work out a new refs/tags/2018-03-22 might be tagged tomorrow\nusing the v2.20.0 tag.\n"},{"id":"372261","messageId":"87imwbmqpg.fsf@fifthhorseman.net","threadId":"50791","inReplyTo":"xmqq1s31ui5s.fsf@gitster-ct.c.googlers.com","subject":"Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Daniel Kahn Gillmor","fromEmail":"dkg@fifthhorseman.net","sentAt":"2019-03-22T05:19:07Z","receivedAt":"2019-03-22T17:23:02Z","isPatch":false,"sender":{"key":"dkg@fifthhorseman.net","avatar":null},"body":"Thanks for the thoughtful feedback, Junio!\n\nOn Thu 2019-03-21 10:31:59 +0900, Junio C Hamano wrote:\n> The other point still stands; there are legitimate reasons people\n> would want to have a tag with v1.0.0 tagname in somewhere that is\n> not refs/tags/v1.0.0 and an extra validation must need to make sure\n> it won't error out, even though warning is probably acceptable.\n\nIt would be great if \"git tag -v\" would present a warning by default in\ncase of a tag name mismatch!  I would not want to rule out making it\npossible to return an error though.\n\nI don't personally have any use case for doing such a tag rename -- you\nmention two:\n\n a) wanting to call tag \"foo\" that you found on remote \"origin\" by the\n    name of \"origin/foo\"\n\n b) wanting to call \"v2.20.0\" by the name \"g2.20.0\"\n\nAnd Ævar mentions a third:\n\n c) mapping versioned tags (e.g. \"v2.20.0\") to tags with a date name\n    (\"2018-03-22\")\n\nI'm not sure how realistic or useful any of these patterns are.  While\n(a) seems the most plausible of the lot to me, none of them are things\ni've ever seen in practice.\n\nSo i'd say that anyone in such a scenario is the outlier, and i wouldn't\nwant the existence of that edge case to make git less useful in the much\nmore common case.\n\nHere's a revised proposal:\n\nConsider a config setting named tag.verifyNameMatch, which can be true,\nfalse, or some sort of sed expression name mangler.\n\n - If set to true, it would do the thing that naive users probably\n   expect when they do \"git tag -v foo\" -- show a warning *and* return\n   an error if the tag message itself doesn't have \"tag foo\" in the\n   \"header section\" of the signed tag.\n\n - If set to false, it wouldn't error out (though maybe it would still\n   show the warning).\n\n - If set to a sed expression, it would feed the name being checked\n   through the sed expression and ensure that the resultant value was\n   present in the signed tag's \"header section\".\n\nThe mangler would work in a pretty straightforward way for (a)\n(e.g. \"s_origin/(.*)_\\1_\") and (b) (e.g. \"s_v(.*)_g\\1_\").\n\ni don't see how it would handle (c), but i think there are probably\nbetter ways to handle (c) (if i'm understanding Ævar's scenario\ncorrectly) than just trying to replay the upstream author's tags with\ndifferent names.  For example, the curator of the repository could just\nmake their own signed tags, based on whatever policy they wanted.  Or,\nthey could just ignore the warnings :P\n\nAs you can probably guess, i'd say that such a tag.verifyNameMatch\nshould default to true, but i'd also be ok if it started off defaulting\nto false, to gather feedback about its impact, and eventually consider\ntransitioning it to true by default.\n\n      --dkg\n"},{"id":"372262","messageId":"87lg17muca.fsf@fifthhorseman.net","threadId":"50791","inReplyTo":"8736nhdvi3.fsf@evledraar.gmail.com","subject":"Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Daniel Kahn Gillmor","fromEmail":"dkg@fifthhorseman.net","sentAt":"2019-03-22T04:00:37Z","receivedAt":"2019-03-22T17:23:03Z","isPatch":false,"sender":{"key":"dkg@fifthhorseman.net","avatar":null},"body":"On Wed 2019-03-20 23:35:48 +0100, Ævar Arnfjörð Bjarmason wrote:\n> But e.g. if you've signed a v1.00 in foo.git, but also maintain bar.git\n> and have a v2.00 there, I can be fooled in foo.git with your proposed\n> change by having the v2.00 bar.git tag pushed to it (just, with the\n> proposed change, not the other way around).\n\nPresumably the tool looking for the \"most interesting new tag\" already\nhas some sort of pattern that it looks for in a tag name (to avoid\naccidentally ingesting some development-specific, non-release tag).\n\nSo yes, this is true for upstreams which issue signed release tags on\nmultiple projects named with the generic form v1.2.3, but it is *not*\ntrue of projects which name their tags the way that (for example)\nGnuPG's upstream does (e.g. gnupg-2.2.14 and libgpg-error-1.36).\n\nIn that case, and the matching pattern itself will exclude tags from\nother repositories.\n\n> It *does* help with the \"pass of an old tag [from the same repository]\"\n> problem, which I'd expect would realistically be the only threat model\n> that matters (forcing a downgrade to an old buggy version), whereas some\n> entirely different project is likely going to be next fed to some\n> project-specific build infrastructure and then won't even build.\n\nI agree that a cross-project tag substitution attack is more exotic than\nan in-project downgrade or freeze attack, but i'm not inclined to wager\non it never being exploitable.  Why take that gamble?\n\n> I wonder if there's a more general fix to be found here that'll have\n> nothing to do with GPG or signed tags per-se. A lot of people have this\n> \"given tags in the repo, what's the latest one?\" problem. I think\n> they'll mostly use the --sort option now, maybe some variant of that\n> which for each <older>/<newer> tag in the chain also checked:\n>\n>     git merge-base --is-ancestor <older> <newer>\n>\n> That would serve as a check for such rouge tags, even if none of them\n> were signed, and a \"they must be signed\" option could be added, along\n> with \"start walking from here\".\n\nI agree that this is a common tag verification use case, and i've seen\nprobably a dozen different attempts to do it which all fail in some\ncurious ways if you assume that the repository being pulled from is\nmalicious.\n\nI like the idea you're describing here, and would be happy to see some\nreasonable, easy-to-use git subcommand that says something like \"find\nthe most interesting tag that derives from the current HEAD\".  for some\nversion of \"interesting\", of course :) It would probably be a good start\nto have \"interesting\" mean:\n\n * the tag name matches some particular pattern\n \n * the tag is cryptographically signed by at least one member of a\n   specific curated keyring\n   \n * the tag is the \"most recent\" or \"farthest descendant\" (these are\n   subtly different, i'm not sure which one makes more sense)\n\nAnyway, the fact that there isn't an obvious perfect answer for how to\ndo this shouldn't stop git from offering a reasonable, well-vetted,\n*good* answer.  Because the current situation just means that every\nproject that cares about verifying signed tags makes up their own\napproach, and i would happily bet that most of them get it wrong in some\ncorner case.\n\nAnd if there's a tool that does a sensible verification of some workflow\nthat we think is reasonable, that tool will also help to encourgae\nprojects to adopt that reasonable workflow.  This is a good thing!\n\n       --dkg\n"},{"id":"372356","messageId":"xmqqpnqgpifu.fsf@gitster-ct.c.googlers.com","threadId":"50791","inReplyTo":"87imwbmqpg.fsf@fifthhorseman.net","subject":"Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-03-24T12:26:13Z","receivedAt":"2019-03-24T12:26:19Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Daniel Kahn Gillmor <dkg@fifthhorseman.net> writes:\n\n> I don't personally have any use case for doing such a tag rename -- you\n> mention two:\n>\n>  a) wanting to call tag \"foo\" that you found on remote \"origin\" by the\n>     name of \"origin/foo\"\n>\n>  b) wanting to call \"v2.20.0\" by the name \"g2.20.0\"\n\nFor the record, in the latter there is no \"wanting to call\".  It was\nmerely a set-up used to illustrate what support there already exists\nin the current system that helps making users aware of tags that are\nnot stored in there \"natural\" place.\n\nThe former however is a natural consequence of noises people make\naround here from time to time, wanting to have tags you grab from\nelsewhere and tags you create locally in separate places.\n"},{"id":"372367","messageId":"878sx4cofr.fsf@evledraar.gmail.com","threadId":"50791","inReplyTo":"87lg17muca.fsf@fifthhorseman.net","subject":"Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2019-03-24T14:55:04Z","receivedAt":"2019-03-24T14:55:10Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Mar 22 2019, Daniel Kahn Gillmor wrote:\n\n> On Wed 2019-03-20 23:35:48 +0100, Ævar Arnfjörð Bjarmason wrote:\n>> But e.g. if you've signed a v1.00 in foo.git, but also maintain bar.git\n>> and have a v2.00 there, I can be fooled in foo.git with your proposed\n>> change by having the v2.00 bar.git tag pushed to it (just, with the\n>> proposed change, not the other way around).\n>\n> Presumably the tool looking for the \"most interesting new tag\" already\n> has some sort of pattern that it looks for in a tag name (to avoid\n> accidentally ingesting some development-specific, non-release tag).\n>\n> So yes, this is true for upstreams which issue signed release tags on\n> multiple projects named with the generic form v1.2.3, but it is *not*\n> true of projects which name their tags the way that (for example)\n> GnuPG's upstream does (e.g. gnupg-2.2.14 and libgpg-error-1.36).\n>\n> In that case, and the matching pattern itself will exclude tags from\n> other repositories.\n>\n>> It *does* help with the \"pass of an old tag [from the same repository]\"\n>> problem, which I'd expect would realistically be the only threat model\n>> that matters (forcing a downgrade to an old buggy version), whereas some\n>> entirely different project is likely going to be next fed to some\n>> project-specific build infrastructure and then won't even build.\n>\n> I agree that a cross-project tag substitution attack is more exotic than\n> an in-project downgrade or freeze attack, but i'm not inclined to wager\n> on it never being exploitable.  Why take that gamble?\n\nFWIW I wasn't arguing that this was a good thing (\"just a point of\nclarification...\"), just walking through and elaborating an exploitable\ncase you mentioned so we're all on the same page as to what the current\nproblem(s) are.\n\n>> I wonder if there's a more general fix to be found here that'll have\n>> nothing to do with GPG or signed tags per-se. A lot of people have this\n>> \"given tags in the repo, what's the latest one?\" problem. I think\n>> they'll mostly use the --sort option now, maybe some variant of that\n>> which for each <older>/<newer> tag in the chain also checked:\n>>\n>>     git merge-base --is-ancestor <older> <newer>\n>>\n>> That would serve as a check for such rouge tags, even if none of them\n>> were signed, and a \"they must be signed\" option could be added, along\n>> with \"start walking from here\".\n>\n> I agree that this is a common tag verification use case, and i've seen\n> probably a dozen different attempts to do it which all fail in some\n> curious ways if you assume that the repository being pulled from is\n> malicious.\n>\n> I like the idea you're describing here, and would be happy to see some\n> reasonable, easy-to-use git subcommand that says something like \"find\n> the most interesting tag that derives from the current HEAD\".  for some\n> version of \"interesting\", of course :) It would probably be a good start\n> to have \"interesting\" mean:\n>\n>  * the tag name matches some particular pattern\n>\n>  * the tag is cryptographically signed by at least one member of a\n>    specific curated keyring\n>\n>  * the tag is the \"most recent\" or \"farthest descendant\" (these are\n>    subtly different, i'm not sure which one makes more sense)\n>\n> Anyway, the fact that there isn't an obvious perfect answer for how to\n> do this shouldn't stop git from offering a reasonable, well-vetted,\n> *good* answer.  Because the current situation just means that every\n> project that cares about verifying signed tags makes up their own\n> approach, and i would happily bet that most of them get it wrong in some\n> corner case.\n>\n> And if there's a tool that does a sensible verification of some workflow\n> that we think is reasonable, that tool will also help to encourgae\n> projects to adopt that reasonable workflow.  This is a good thing!\n>\n>        --dkg\n"},{"id":"372368","messageId":"87k1goia52.fsf@fifthhorseman.net","threadId":"50791","inReplyTo":"xmqqpnqgpifu.fsf@gitster-ct.c.googlers.com","subject":"Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Daniel Kahn Gillmor","fromEmail":"dkg@fifthhorseman.net","sentAt":"2019-03-24T15:07:21Z","receivedAt":"2019-03-24T15:45:27Z","isPatch":false,"sender":{"key":"dkg@fifthhorseman.net","avatar":null},"body":"On Sun 2019-03-24 21:26:13 +0900, Junio C Hamano wrote:\n> Daniel Kahn Gillmor <dkg@fifthhorseman.net> writes:\n>\n>> I don't personally have any use case for doing such a tag rename -- you\n>> mention two:\n>>\n>>  a) wanting to call tag \"foo\" that you found on remote \"origin\" by the\n>>     name of \"origin/foo\"\n>>\n>>  b) wanting to call \"v2.20.0\" by the name \"g2.20.0\"\n>\n> For the record, in the latter there is no \"wanting to call\".  It was\n> merely a set-up used to illustrate what support there already exists\n> in the current system that helps making users aware of tags that are\n> not stored in there \"natural\" place.\n>\n> The former however is a natural consequence of noises people make\n> around here from time to time, wanting to have tags you grab from\n> elsewhere and tags you create locally in separate places.\n\nGotcha, thanks.  I like the warnings that are already showing up from\n(b) So I won't worry about (b) as a justification then, but rather keep\nmy focus on (a).  (and i still think that (c) has better solutions than\ntag renaming)\n\nWhat do you think of my updated proposal for tag.verifyNameMatch ?\n\n     --dkg\n"},{"id":"372392","messageId":"xmqqh8brofid.fsf@gitster-ct.c.googlers.com","threadId":"50791","inReplyTo":"87k1goia52.fsf@fifthhorseman.net","subject":"Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-03-25T02:27:06Z","receivedAt":"2019-03-25T02:27:10Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Daniel Kahn Gillmor <dkg@fifthhorseman.net> writes:\n\n\n> What do you think of my updated proposal for tag.verifyNameMatch ?\n\nMeh to slightly negative for hard-coding project-specific preference\nto the core tools.  \"We give you --format so go wild in your project\nto do verification your project likes.\" I think was the conclusion of\nthe previous round of discussions, and I do not think we saw any new\narguments in this round to rethink it in a different way.\n\n\n"},{"id":"372531","messageId":"87ftr9h72a.fsf@fifthhorseman.net","threadId":"50791","inReplyTo":"xmqqh8brofid.fsf@gitster-ct.c.googlers.com","subject":"Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Daniel Kahn Gillmor","fromEmail":"dkg@fifthhorseman.net","sentAt":"2019-03-26T17:35:57Z","receivedAt":"2019-03-26T17:36:05Z","isPatch":false,"sender":{"key":"dkg@fifthhorseman.net","avatar":null},"body":"On Mon 2019-03-25 11:27:06 +0900, Junio C Hamano wrote:\n> Daniel Kahn Gillmor <dkg@fifthhorseman.net> writes:\n>\n>> What do you think of my updated proposal for tag.verifyNameMatch ?\n>\n> Meh to slightly negative for hard-coding project-specific preference\n> to the core tools.  \"We give you --format so go wild in your project\n> to do verification your project likes.\" I think was the conclusion of\n> the previous round of discussions, and I do not think we saw any new\n> arguments in this round to rethink it in a different way.\n\nHm, maybe --format is all that's necessary to resolve the concerns about\nerrors affecting scenario (a) ?  If that's the case, then maybe the path\nforward is a warning on tagname mismatch (and maybe i can convince you\nlater than an actual error could be acceptable :P)\n\nBut I don't see how to use --format with \"git tag -v\" at all.  Can you\nshow me what i'm doing wrong?  git-tag(1) says that --format defaults to\n'%(refname:strip=2)', but git tag -v behaves differently when i specify\nthat same default explicitly:\n\n    0 dkg@alice:~/src/pkg-gnupg/gnupg2$ git tag -v gnupg-2.2.13\n    object 7922e2dd1c7eee48a8a2cf4799827942489ddd0f\n    type commit\n    tag gnupg-2.2.13\n    tagger Werner Koch <wk@gnupg.org> 1549985965 +0100\n\n    You may want to watch the Ellsberg/Chomsky discussion\n    at <https://riseuptimes.org/2018/04/25/daniel-ellsberg-and-noam-chomsky-discuss-nuclear-war/>\n    or at <https://theintercept.com/chomsky-ellsberg/>\n    gpg: Signature made Tue 12 Feb 2019 04:41:32 PM CET\n    gpg:                using RSA key D8692123C4065DEA5E0F3AB5249B39D24F25E3B6\n    gpg: Good signature from \"Werner Koch (dist sig)\" [full]\n    Primary key fingerprint: D869 2123 C406 5DEA 5E0F  3AB5 249B 39D2 4F25 E3B6\n    0 dkg@alice:~/src/pkg-gnupg/gnupg2$ git tag -v --format='%(refname:strip=2)' gnupg-2.2.13\n\n    0 dkg@alice:~/src/pkg-gnupg/gnupg2$ \n\nWhat am i missing?\n\n     --dkg\n"},{"id":"372540","messageId":"20190326184001.GD24105@sigill.intra.peff.net","threadId":"50791","inReplyTo":"87ftr9h72a.fsf@fifthhorseman.net","subject":"Re: git tag -v should verify that the tag signer intended the same tag name as the user is verifying","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-03-26T18:40:01Z","receivedAt":"2019-03-26T18:40:05Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Mar 26, 2019 at 06:35:57PM +0100, Daniel Kahn Gillmor wrote:\n\n> But I don't see how to use --format with \"git tag -v\" at all.  Can you\n> show me what i'm doing wrong?  git-tag(1) says that --format defaults to\n> '%(refname:strip=2)', but git tag -v behaves differently when i specify\n> that same default explicitly:\n\nHmm.\n\nI think the documentation is unclear. For a normal listing of tags,\nthe default format is the stripped refname, and you can override it with\n--format.\n\nFor \"-v\", the default is to dump the whole tag contents (i.e.,\ntraditionally it just ran \"verify-tag -v\" under the hood, though I think\nit is all done internally now).\n\nSo this doesn't surprise me:\n\n>     0 dkg@alice:~/src/pkg-gnupg/gnupg2$ git tag -v gnupg-2.2.13\n>     object 7922e2dd1c7eee48a8a2cf4799827942489ddd0f\n>     type commit\n>     tag gnupg-2.2.13\n>     tagger Werner Koch <wk@gnupg.org> 1549985965 +0100\n> \n>     You may want to watch the Ellsberg/Chomsky discussion\n>     at <https://riseuptimes.org/2018/04/25/daniel-ellsberg-and-noam-chomsky-discuss-nuclear-war/>\n>     or at <https://theintercept.com/chomsky-ellsberg/>\n>     gpg: Signature made Tue 12 Feb 2019 04:41:32 PM CET\n>     gpg:                using RSA key D8692123C4065DEA5E0F3AB5249B39D24F25E3B6\n>     gpg: Good signature from \"Werner Koch (dist sig)\" [full]\n>     Primary key fingerprint: D869 2123 C406 5DEA 5E0F  3AB5 249B 39D2 4F25 E3B6\n\nBut this does:\n\n>     0 dkg@alice:~/src/pkg-gnupg/gnupg2$ git tag -v --format='%(refname:strip=2)' gnupg-2.2.13\n\nI'd expect it to print the tagname here. It looks like we only feed the\npartial tagname to the ref-formatting machinery, so the \"strip\" doesn't\ndo what you'd expect.\n\nIt also doesn't show the gpg output, though it does actually verify the\ntag. But AFAIK there's no format specifier in the ref-filter language\nfor showing the GPG output! What a mess.\n\n-Peff\n"}]}