Hi,
I propose to increase the security of this repository requiring a GPG sign verification for every commits, _脿 la Linux kernel_.
Of course, it can be a bit intimidating for new committers, but NodeJS is a very popular JavaScript runtime and we should try to implement the maximum level of security available to prevent any tampering with it.
As a fallback, I suggest at least to require the GPG sign for every stable collaborator.
What do you think about it guys?
No strong opinion on this, just some thoughts:
master
branch due to rebasing.I'm not really certain this would do any good, and it would probably be lost through our branch management anyways.
I'd be ok with having this be for _releasers_ doing _releases_ though, including myself.
The main benefit is to prevent that someone can push a commit with an arbitrary user.name
and user.email
in their .gitconfig
without having a proof that proves the identity is correct, that is the non-repudation property.
As you can see on this repository you have both started to contribute to my brand new repository: https://github.com/phra/git-author-commit/commits/master
Only the latest commit can be trusted because it's GPG signed.
_Just my two cents._
Collaborators and contributors are free to sign commits as they like at the moment. Don't get me wrong, signing commits does add to security and I approve doing so, but I don't see much value in enforcing this behavior at the moment.
As you can see on this repository you have both started to contribute to my brand new repository:
And signing my commits in this repository would not have prevented that.
The problem with GPG signatures is that you can say "yes, that's mine", but not "nope, that's not mine". You could still push unsigned commits with my email address and name, they just won't have the green badge.
(By the way, I would be careful with that, depending on your country of residence, online impersonation and/or resulting harm for those who have been impersonated can be considered a federal crime.)
Sure, it is a valid point that having all contributors sign all commits would allow us to be certain that they are indeed the author of the commit, but as long as we require all changes to be proposed via PRs which we manually review, we know who actually pushed the code. (And if you want to make some great contributions and put my name under them, please, go ahead.)
Furthermore, we accept (and have collaborators that submit) anonymous and pseudonymous contributions. Mandating GPG signing doesn't full-out prohibit that but it makes the barrier to entry much higher.
Ok, I'm already positive towards the fact that you can see the security benefits of GPG signed commits besides the existing protections, that was my goal actually. :slightly_smiling_face:
Just keep in mind that the same _attack_ that I've done on my own repository impersonating you can be replicated by anyone that has write permission on the Node.js repository itself and GPG signs can effectively prevent that. :slightly_smiling_face:
You are free to close the ticket.
Personally, I would be okay with requiring people with write access to this repository to sign commits which they push to public branches (not including PRs), many collaborators already do so.
@tniessen that would be already a big improvement! :100:
As you can see on this repository you have both started to contribute to my brand new repository: https://github.com/phra/git-author-commit/commits/master
Right - at least I've known about this for a long time already.
Our existing crosslinking policies already mitigate this though as all (except some release) commits have references to discussions in the issue tracker. That makes it much easier to find if a commit wasn't what was agreed upon.
I've sent a report to GitHub via HackerOne to ask for a visual feedback when the authors of commit/push don't match (like the Verified
badge) and for an opt-in option to globally forbid pushing commits that pretend to be authored by us but they are not GPG signed. I can keep you updated about their response.
globally forbid pushing commits that pretend to be authored by us but they are not GPG signed
I might miss your point here, but I don't think this is going to work. If I push a signed commit and someone else cherry-picks it onto another branch, he won't be able to push it?
@tniessen if the commit is GPG signed it can freely be used by anyone and you can keep the authorship. Other people should also be able to push GPG signed commits from other authors. (if they were not edited after the sign of course)
I can copy a piece of the report to describe what I mean:
There are three different levels of trustiness about a commit as I can see:
- GPG Signed: a GPG sign is attached to the commit effectively proving the authorship regardless of the user that is pushing it
- Authenticated: the user that is pushing the commit is the same that has authored the commit itself.
- Not Authenticated/Anonymous: the commit is not GPG signed and the user that is pushing the commit differs from the user that pretends to have authored the commit itself.
### Proposed solutions
- At the moment is only possible to visually distinguish between 1st and 2nd cases with the "Verified" badge, but it would be ideal also have a visual feedback to distinguish between 2nd and 3rd scenarios.
- Implement an opt-in option in personal settings to forbid any push of not-signed commits that pretends to be authored by us.
so the _opt-in_ option that i'm thinking about will only affect not signed commits if enabled.
if the commit is GPG signed it can freely be used by anyone and you can keep the authorship.
If I am not mistaken, the SHA of the tree object is part of the signature, therefore rebasing / cherry-picking / merging would invalidate and thus remove the signature, right? I think it is not the author but the committer who signs a commit.
@tniessen uhm.. actually you are right I think, I was not remembering that a commit points to the previous one! thanks for noticing it!
Yep, keeping authorship (i.e. the original GPG sign) when altering the previous history of a GPG signed commit can be a problem.. maybe an acceptable trade-off can be to keep authorship + sign when working with commits without altering the previous history, e.g. forks, but discarding the authorship if someone apply that commit to a different git history. (it's effectively a different commit)
GitHub response:
Hi,
Thanks for the submission!
This is working as designed, and we are aware there are ways tracking commit attribution can be improved.
We've considered some of your proposed solutions in the past, and we may make commit attribution more refined in the future, but don't have anything to announce now.
As a result, this is not eligible for reward under the Bug Bounty program.
Best regards and happy hacking!
Brent
so yeah, at the moment the most acceptable tradeoff is @tniessen's proposal:
Personally, I would be okay with requiring people with write access to this repository to sign commits which they push to public branches (not including PRs), many collaborators already do so.
EDIT: btw it would be nice to have a personal, not global opt-in option to prevent not GPG signed commits to be pushed pretending that are authored by you on a particular repository.
Because releasers manually take commits from masters to releases and review what they're releasing, and those already have PGP keys and are signed - I don't see the point.
This would only potentially help people building directly from master
and not a release which I don't think justifies the overhead.
-1 from me on it.
I don't see the point.
Did you see this?
As I said in my first comment to this issue:
The main benefit is to prevent that someone can push a commit with an arbitrary
user.name
anduser.email
in their.gitconfig
without having a proof that proves the identity is correct, that is the non-repudation property.
It's not about opinions on _overhead_, but non-repudiation
property, that a cumulative signature cannot guarantee.
By the way, maybe I've found the right requirement:
Every commits that appears on master branch MUST be GPG-signed.
I think that this can be the optimal trade-off because master
branch should be immutable, so no problem with git rebase
_et alia_.
Releasers can simply cherry-pick GPG-signed commits and then GPG-sign the release as well, with all the security benefits of it.
What do you think about this?
The value simply isn't that big because of how the project is structured and it might scare away contributors. So yeah, I don't see it happening.
The value simply isn't that big because of how the project is structured and it might scare away contributors.
This requirement would only affect collaborators, as all non-collaborator PRs are rebased onto master anyway.
This would only potentially help people building directly from master and not a release which I don't think justifies the overhead.
There isn't really much overhead, you just set up your gpg keys, do git config --global commit.gpgsign true
, and that's it. You do have to enter your gpg key password once per session, but that's not exactly a huge effort.
We do (I think) limit access to release branches (see https://github.com/nodejs/Release/issues/199), and pushes to those branches would be much more obvious.
I don't see the downside to requiring this
Furthermore, we accept (and have collaborators that submit) anonymous and pseudonymous contributions. Mandating GPG signing doesn't full-out prohibit that but it makes the barrier to entry much higher.
I don't think it makes it higher, you just use the same name/email in your gpg key that you use in your Github account (and in your commits). Same as an ssh key. Github just checks that the key used matches the one you save in your account.
Collaborators use 2FA on GitHub, so the only way for a third party to push to this repository (that I know of) is by somehow retrieving one of the personal access tokens.
Or by retrieving the private ssh key of a collaborator, which doesn't seem impossible, if you don't password protect your ssh key, then it's just stored in plaintext in ~/.ssh
.
Signing every commit does not enhance security further than signing the last commit of each change set from a single author.
Sure, but it's easier for both collaborators and people checking to just sign all commits automatically.
I think the first step would be to add a note to the COLLABORATOR_GUIDE recommending that people enable gpg signing, and then to ask people who currently don't sign their commits whether they would be willing to. If no-one has a strong objection to requiring gpg signatures for commits then we can consider making it mandatory (although I'm not sure how we'd enforce it without protecting the branch, which would prevent force pushing).
I don't see the downside to requiring this
The downside is that there is no real upside, IMO, just more hassle. It doesn't significantly increase security like e.g. 2FA does.
Or by retrieving the private ssh key of a collaborator, which doesn't seem impossible
Maybe not (although I hope and assume everyone encrypts their private key) but there is not much damage an attacker could cause. Any vandalism would be restored within minutes.
Maybe not (although I hope and assume everyone encrypts their private key) but there is not much damage an attacker could cause. Any vandalism would be restored within minutes.
If someone were to land a commit that was slightly modified to master, would anyone notice? I'd say probably not. It's quite possible that someone could make changes to code that were not detected before being included in a release. I don't think the attack vector is "someone deleting stuff", it'd be someone adding backdoors to the code.
We get close to a hundred commits a week, and AFAIK no-one checks the majority of them.
FWIW you can check how many people don't have GPG enabled with:
git log --since="one month" --pretty=format:"%h %cn" |
while read i; do test "$(git verify-commit ${i%% *} 2>&1)" || echo ${i#* }; done |
sort | uniq
although I hope and assume everyone encrypts their private key
Also in my experience this is far from being the case.
@gibfahn thanks for one liner, i will put it as an alias in my shell!
although I hope and assume everyone encrypts their private key
actually i hope that people also encrypt HDDs and SSDs, at least the ones with a privileged access to nodejs repository because in theory if you don't encrypt your HDD i can physically remove it, backdoor it, put it back again and just wait for you to write the password on the keyboard, after having copied the encrypted key, of course!
FYI GitHub enabled GPG signatures for actions taken on the website (like a PR merge) that involves GPG signed commits, so basically every commit that is signed locally will be re-signed by GitHub if required.
in their reply, they said:
We've considered some of your proposed solutions in the past, and we may make commit attribution more refined in the future, but don't have anything to announce now.
so probably they were thinking about this feature that was not ready at that time yet.
this means that if people will enable GPG locally, it's possibile to have the entire git history GPG signed for additional protection against tampering.
just my 2 cents :money_with_wings:
this means that if people will enable GPG locally, it's possibile to have the entire git history GPG signed for additional protection against tampering.
We don't use the Github merging features at all, so that wouldn't be a problem anyway.
I end up using a number of different machines including some shared ones. I worry that gpg signing will either limit where I can commit from (making me less efficient) or I'm going to have more work moving keys around. Is this unjustified ?
@mhdawson signing is done at commit time, and as all commits are rebased on master, you'd only have to have gpg keys on the machine you use to land commits.
Moving gpg keys is about as painful as moving ssh keys in my experience, so not hugely painful. But this is the question, is it's going to make people's workflows harder then that's a reason not to do it.
If we have an commit landing queue, then that avoids the question entirely.
@mhdawson @gibfahn i personally use this strategy for backing up my keys:
BACKUP
gpg2 --full-generate-key
gpg2 --send-keys B52FAC34A07EB53F340E985491FF93D1B85D76B5
gpg2 --export-secret-keys --armor | gpg2 --encrypt --sign --armor -r [email protected] > .phra.asc
MANUAL STEP
RESTORE
gpg2 --recv-keys B52FAC34A07EB53F340E985491FF93D1B85D76B5
gpg2 --edit-key [email protected] trust
wget -O ~/.phra.asc <gist_url>
gpg2 ~/.phra.asc
gpg2 --import ~/.phra
shred -zuvn 3 ~/.phra
_restore function in my .bash_aliases:_
upgrade_gpg_keys() {
gpg2 --recv-keys B85D76B5 &&
gpg2 --edit-key [email protected] trust &&
wget -O ~/.phra.asc <gist_url> &&
gpg2 ~/.phra.asc &&
gpg2 --import ~/.phra &&
shred -zuvn 3 ~/.phra
}
GIT CONFIGURATION
then to configure git you have to update its configuration:
git config --global user.signingkey B52FAC34A07EB53F340E985491FF93D1B85D76B5
git config --global commit.gpgsign true
GPG CONFIGURATION _optional_
if you want to be able to check GitHub's signatures you have to import its key:
gpg2 --recv-keys 4AEE18F83AFDEB23
gpg2 --edit-key [email protected] trust
git config --global user.signingkey B52FAC34A07EB53F340E985491FF93D1B85D76B5
FWIW you don't need to do this if you only have one key which has the same email as git config --global user.email
.
@gibfahn yes, I have at least 3-4 different machines that I might use for landing changes.
I do not see this happening, so I am closing the issue. If we consider else wise, we can still reopen this.
Thanks a lot for bringing this subject up.
Most helpful comment
I'm not really certain this would do any good, and it would probably be lost through our branch management anyways.
I'd be ok with having this be for _releasers_ doing _releases_ though, including myself.