Most git servers have an option to only allow commits to go through if the ssh key that is pushing the commit matches the SSH key associated with the account of the "Author" field. Easier to implement than enforcing PGP signing.
Sounds impractical in the case of GitHub though. If I create a repo, you fork my repo, I push some commits to mine, then you pull from mine and author some more commits and then I delete my repo then you can’t push.
It's also remarkable because it's fear-mongering. It's not a "problem," and most developers would be mad if they stopped getting credit for their pull requests in projects using a rebase workflow, which is what their "solution" would require. (See my other comment for details.)
Technically, it is the same "problem" as falsely writing "this proofs P = NP" into the commit message. It's just free text, you can put whatever you want there (as long as the email address is formatted correctly, I guess).
I will admit that GitHub formats the commit in a way where it looks like the commit author may have been verified in some way (because it's linked to a GitHub account, and approximately no other type of online service permits posting things from an account without actually being from that account - the PGP keyservers are the only other one I can think of!), and the content of commit messages don't look like they're endorsed by GitHub.
I'm not sure if there's an easy way in the UI to demonstrate unverified/verified, though. Even a small broken-lock icon would imply that something is wrong when it's not really wrong, it's just common practice for this to be entirely based on trust.
Perhaps it would help to show the verified identity of the user who pushed the commit to GitHub alongside the unverified author?
I found this out when I was migrating code from hg in google code (now archived) to github. The source commits didn't have valid email addresses so they didn't work very well with git and github, so I just rewrote them to something else. There's no special checks that a commit came from the owner of an email address, and there's no way to prove it did/didn't.
Git is cryptographically secure, but it's not foolproof.
However signing a single commit verifies the parent commits (similar to the blockchain) so it isn't necessary for every commit.
Signing tags and commits is great, but if you decide to use this in your normal workflow, you’ll have to make sure that everyone on your team understands how to do so. If you don’t, you’ll end up spending a lot of time helping people figure out how to rewrite their commits with signed versions. Make sure you understand GPG and the benefits of signing things before adopting this as part of your standard workflow.
Git offers the _option_ to sign commits. Git itself makes no guarantees that a commit's author is who it's listed to be, unless you use signed commits.
Signing a commit does not verify parent commits in the way I think you think it does. It does give the guarantee of 'These are the commits that are the basis of my commit', but that is only worth as much as what your signature actually conveys. Your signature certainly conveys you authored your commit, but it doesn't guarantee that the parent commit was authored by who was listed as the author.
Linus certainly doesn't see this as a goal of Git. Against what threats does the cryptography protect? Has anyone published the threat model of Git? Things I worry about:
1. Can I reorder commits without access to secret keys?
2. What if one secret key is compromised, do I have to resign all my old commits with the new secret key? How do I do that?
3. How do I ensure my list of authorized keys is the same as yours?
4. Can I easily detect that my code signing key has been compromised?
5. How do you prevent a Pull Request that contains a unittest that when run exfils your keys, opens a shell, injects source code or backdoors git?
Really appreciate your answers. I've wondered about this stuff for a while but never had the time to read through the Git source code.
>No, because a hash of some commit data is what’s signed and the parent is part of that.
How does this work with cherry picks or rebases? Would it just be authorized by the key of the person doing the rebase and lose the authentication of the original commits? How would this complicate say forensics investigation attempting to understand how authored a backdoor?
>I don’t understand that question. Can you expand on it?
Lets say I am a member of an organization and I am syncing a git repo for the first time. How do I ensure that the code I am getting was only authored by members of that organization? Who does the work of adding new keys for new members, revoking old keys when employees leave or keys are compromised? How does everyone agree on this key set?
> No, and the same goes for pretty much anything else that can be compromised.
I agree to determining key compromise is impossible but the detection of use of compromised keys in a suspectious manner is certainly possible. Consider a chain of one-use keys where each key is only used once per commit and then deleted. Using a key twice triggers alarms and emails.
>You read it before you run it.
You should read it before you run it however everyone makes mistakes and detecting underhanded programming techniques is hard. One could imagine a source code system that would warn users that the code they are about to run has not been authored by anyone in their organization.
> How does this work with cherry picks or rebases? Would it just be authorized by the key of the person doing the rebase and lose the authentication of the original commits?
Yes.
> ⋮
Sounds like your organization will need to put a lot of new stuff on top of PGP and Git, then.
Signing a commit does "sign" all previous commits, but it doesn't verify that they are actually yours, you still have to manually do that. If someone slips in a "fake commit" either directly on to your machine, or does it to remote and you pull it down and commit and sign a tag, you won't get any kind of notification there is an issue.
IMO it's better to sign all commits, as then it gets you in the habit of knowing how it's done, you are less likely to make mistakes while doing it, and you can add tooling that will sound alarms at the first unsigned commit.
It does leave you more vulnerable to keyloggers, and gives more instances where your key is decrypted and used, but I personally think that's a better problem to have rather than having to manually verify every single commit isn't forged before you sign and tag.
There's a very good reason Git (and GitHub) permit this: maintaining credit when rebasing or making other minor edits. If you submit some code to me, and I pull --rebase your branch into the project, the resulting commit won't be byte-for-byte identical to the one you sent me. At the very least, the parent commit pointer needs to be different, and Git will also update the committer (to myself) and commit timestamp. Since git stores trees, not diffs, the resulting tree will probably be different, and if there are merge conflicts, then the diff itself will also be different from the diff you sent me. If I fix a typo in a comment or something and then incorporate the commit, that will also be different.
If Git implemented something with commit signing as a matter of course, this functionality would be broken. I couldn't directly attribute the commit to you; it would be signed with my key instead, because your original signature won't be valid. I could of course put your name in the commit message, but then the "forgery" problem arises again: I can just put anyone's name right there, of course.
The current system ensures that you get credit for your work (and it's machine-parseable credit, so it shows up in your GitHub profile's contribution history) when someone rebases a commit you wrote, instead of the project maintainer getting credit.
Hey HN -- one of the creators here. I saw a few people mention this in the comments and want to re-iterate: this is NOT a bug on GitHub. This is a feature of Git that GitHub has to support because we often need to push commits on behalf of other users.
However -- this does illustrate a clear reason why it sometimes makes sense to PGP-sign your releases/commits.
Yeah, I figure you all know that :) I just think calling it "forgery" / "fraudulent" makes it sound like a Git/GitHub vulnerability. It's a feature that depends on trust and goodwill, and the fact that trust can be abused isn't interesting.
For instance, if I wrote "Hey HN, one of the creators here" when I'm not, people wouldn't call that "HN comment forgery" - they'd just call it regular lying.
Also I looked at your actual product (a U2F implementation that forwards things to your phone) and it seems pretty cool! Definitely more secure than TOTP. You should Show HN that :-)
There is no fundamental difference between a commit message and the commit author, its just some meta information attached to the commit. It's up to whoever is responsible to merge pull requests to check if this commit is actually coming from the person you think it is. Signed commits are one option, others would be to send the commit as a patch via mail (also possibly signed), or to open a pull request as a logged in user on an auxiliary meta-platform (which is exactly what Github is).
This is true but on the other hand anyone making a serious effort to fix the raging dumpster fire which is PGP usability deserves some kudos. Most people who turn GPG signing on in Git seem to turn it off after hitting one of the many UX failures.
you can use a gpg key to sign your commits and tell github about your public key so they can add a verified badge in the commit log. really only useful if github can enforce authenticity when pushing to repos...
Is this working? I just tried it and it generates a commit hash that leads to a 404 page[1]. I haven't looked into what the code is doing, but for it to claim that it stole my identity is very misleading.
This didn't quite work for me since I had my github username changed (caleb-davenport to calebdavenport) about a year ago. It used my old username instead.
Not sure how gitlab handles the avatar, but in practice this doesn't matter internally in a FLOSS project:
"The commit that broke something is attributed to Sojourner Truth. That's you, right?"
"Yes, that's me."
However, a centralized identity in a global namespace that merely wraps around arbitrary state entered into a local instance of git instance is not gonna go good.
The title is misleading, the text itself is sensationalist and over promotting their own product.
Git authors are simply names associated to commits, it's not supposed to authenticate anyone, so talking "forgery" is just nonsense.
Any repository owners worried about the authenticity of the commits should allow only signed commits. This is available in all major git platforms AFAIK.
49 comments
[ 3.4 ms ] story [ 109 ms ] thread1. Clear problem every developer has (most don't even know !!)
2. Inform on how to solve the problem
3. Offer the convenient solution.
Wow.
To me it is a problem and I'm glad they are pointing it out. I suspected this was possible but wasn't sure, now I know for sure.
Edit: Github actually marks verified commits in their GUI: https://help.github.com/assets/images/help/commits/gpg-signe...
I'm not sure if there's an easy way in the UI to demonstrate unverified/verified, though. Even a small broken-lock icon would imply that something is wrong when it's not really wrong, it's just common practice for this to be entirely based on trust.
Perhaps it would help to show the verified identity of the user who pushed the commit to GitHub alongside the unverified author?
You don't even need to edit ~/.gitconfig file. Just set GIT_AUTHOR_NAME / GIT_AUTHOR_EMAIL / GIT_AUTHOR_DATE env variables to anything you want. See https://git-scm.com/book/en/v2/Git-Internals-Environment-Var... for more variables.
Take commit metadata with a grain of salt.
However signing a single commit verifies the parent commits (similar to the blockchain) so it isn't necessary for every commit.
Signing tags and commits is great, but if you decide to use this in your normal workflow, you’ll have to make sure that everyone on your team understands how to do so. If you don’t, you’ll end up spending a lot of time helping people figure out how to rewrite their commits with signed versions. Make sure you understand GPG and the benefits of signing things before adopting this as part of your standard workflow.
Signing a commit does not verify parent commits in the way I think you think it does. It does give the guarantee of 'These are the commits that are the basis of my commit', but that is only worth as much as what your signature actually conveys. Your signature certainly conveys you authored your commit, but it doesn't guarantee that the parent commit was authored by who was listed as the author.
Linus certainly doesn't see this as a goal of Git. Against what threats does the cryptography protect? Has anyone published the threat model of Git? Things I worry about:
1. Can I reorder commits without access to secret keys?
2. What if one secret key is compromised, do I have to resign all my old commits with the new secret key? How do I do that?
3. How do I ensure my list of authorized keys is the same as yours?
4. Can I easily detect that my code signing key has been compromised?
5. How do you prevent a Pull Request that contains a unittest that when run exfils your keys, opens a shell, injects source code or backdoors git?
Not right now, because it still uses SHA-1. But apart from that, the answers are:
> 1. Can I reorder commits without access to secret keys?
No, because a hash of some commit data is what’s signed and the parent is part of that
> 2. What if one secret key is compromised, do I have to resign all my old commits with the new secret key?
No, just make a new commit on top with the new key explicitly explaining that you trust the old stuff
> 3. How do I ensure my list of authorized keys is the same as yours?
I don’t understand that question. Can you expand on it?
> 4. Can I easily detect that my code signing key has been compromised?
No, and the same goes for pretty much anything else that can be compromised.
> 5. How do you prevent a Pull Request that contains a unittest that when run exfils your keys, opens a shell, injects source code or backdoors git?
You read it before you run it.
>No, because a hash of some commit data is what’s signed and the parent is part of that.
How does this work with cherry picks or rebases? Would it just be authorized by the key of the person doing the rebase and lose the authentication of the original commits? How would this complicate say forensics investigation attempting to understand how authored a backdoor?
>I don’t understand that question. Can you expand on it?
Lets say I am a member of an organization and I am syncing a git repo for the first time. How do I ensure that the code I am getting was only authored by members of that organization? Who does the work of adding new keys for new members, revoking old keys when employees leave or keys are compromised? How does everyone agree on this key set?
> No, and the same goes for pretty much anything else that can be compromised.
I agree to determining key compromise is impossible but the detection of use of compromised keys in a suspectious manner is certainly possible. Consider a chain of one-use keys where each key is only used once per commit and then deleted. Using a key twice triggers alarms and emails.
>You read it before you run it.
You should read it before you run it however everyone makes mistakes and detecting underhanded programming techniques is hard. One could imagine a source code system that would warn users that the code they are about to run has not been authored by anyone in their organization.
Yes.
> ⋮
Sounds like your organization will need to put a lot of new stuff on top of PGP and Git, then.
IMO it's better to sign all commits, as then it gets you in the habit of knowing how it's done, you are less likely to make mistakes while doing it, and you can add tooling that will sound alarms at the first unsigned commit.
It does leave you more vulnerable to keyloggers, and gives more instances where your key is decrypted and used, but I personally think that's a better problem to have rather than having to manually verify every single commit isn't forged before you sign and tag.
If Git implemented something with commit signing as a matter of course, this functionality would be broken. I couldn't directly attribute the commit to you; it would be signed with my key instead, because your original signature won't be valid. I could of course put your name in the commit message, but then the "forgery" problem arises again: I can just put anyone's name right there, of course.
The current system ensures that you get credit for your work (and it's machine-parseable credit, so it shows up in your GitHub profile's contribution history) when someone rebases a commit you wrote, instead of the project maintainer getting credit.
However -- this does illustrate a clear reason why it sometimes makes sense to PGP-sign your releases/commits.
For instance, if I wrote "Hey HN, one of the creators here" when I'm not, people wouldn't call that "HN comment forgery" - they'd just call it regular lying.
Such features can be a vulnerability, a vulnerability does not have to be an accident
>the fact that trust can be abused isn't interesting
As a security researcher it is interesting to me but clearly YMMV
git commit --author="Some Name <some@name.org>"
Or commit to the future:
git commit --author="Zager Evans <zager@evans.com>" --date="Fri Aug 3 14:00 2525 +0000"
There is no fundamental difference between a commit message and the commit author, its just some meta information attached to the commit. It's up to whoever is responsible to merge pull requests to check if this commit is actually coming from the person you think it is. Signed commits are one option, others would be to send the commit as a patch via mail (also possibly signed), or to open a pull request as a logged in user on an auxiliary meta-platform (which is exactly what Github is).
authentic commit: https://github.com/bsdlp/packagebot/commit/c7cd115357f51e8e1...
you can use a gpg key to sign your commits and tell github about your public key so they can add a verified badge in the commit log. really only useful if github can enforce authenticity when pushing to repos...
[1] - https://github.com/git-forge/fraudulent/commit/a0a2c80140bae...
https://github.com/git-forge/fraudulent/commit/f9f2b8b6f2711...
"The commit that broke something is attributed to Sojourner Truth. That's you, right?"
"Yes, that's me."
However, a centralized identity in a global namespace that merely wraps around arbitrary state entered into a local instance of git instance is not gonna go good.
The title is misleading, the text itself is sensationalist and over promotting their own product.
Git authors are simply names associated to commits, it's not supposed to authenticate anyone, so talking "forgery" is just nonsense.
Any repository owners worried about the authenticity of the commits should allow only signed commits. This is available in all major git platforms AFAIK.