Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable GPG verification for Casks. #4120

Closed
wants to merge 5 commits into from

Conversation

reitermarkus
Copy link
Member

@reitermarkus reitermarkus commented Apr 29, 2018

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same change?
  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes? Here's an example.
  • Have you successfully run brew style with your changes locally?
  • Have you successfully run brew tests with your changes locally?

@BrewTestBot BrewTestBot added the in progress Maintainers are working on this label Apr 29, 2018
@commitay commitay added the cask Homebrew Cask label Apr 29, 2018
@@ -18,7 +18,7 @@ def initialize(cask, downloaded_path)

def verify
return unless self.class.me?(cask)
ohai "Verifying checksum for Cask #{cask}"
ohai "Verifying SHA256 checksum for Cask #{cask}”."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using left and right double quotes isn't consistent with other cask messages.

end

def verify
return unless available? && cask.gpg.signature != :embedded
unless available?
ohai "GPG is not installed, skipping verification of GPG signature for Cask “#{cask}”."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'gnupg' formula is not installed


@command.run!("gpg",
@command.run!(Formula["gnupg"].opt_bin/"gpg",
args: ["--verify", sig, downloaded_path],
print_stdout: true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this printing to stdout.

@ghost ghost assigned reitermarkus May 4, 2018
@reitermarkus reitermarkus force-pushed the gpg-verification branch 4 times, most recently from df18de0 to 01f161e Compare May 8, 2018 01:56
@reitermarkus reitermarkus requested a review from a team May 9, 2018 17:54
@commitay
Copy link
Contributor

commitay commented May 9, 2018

Should we be adding keys to the users default keyring?

@reitermarkus
Copy link
Member Author

We aren't auto-trusting the keys, so I think it's fine to use the default keyring.

@commitay
Copy link
Contributor

commitay commented May 9, 2018

Yeah, but the only way to avoid having keys added to the default keyring is to uninstall gnupg?

Homebrew/Cask doesn't modify "user config" type files (usually ignoring them or overriding them with our own config) so it feels weird that we're kind of doing the opposite with this.

@reitermarkus
Copy link
Member Author

Ok, changed it to use a custom homebrew-keyring.gpg instead.

@commitay
Copy link
Contributor

Tried this in a clean VM, the error is reproducible with all the Casks I've tried so far.

==> Failed command:
/usr/local/opt/gnupg/bin/gpg --no-default-keyring --keyring /Users/commitay/Library/Caches/Homebrew/gpg/homebrew-keyring.gpg --receive-keys 9d17e656bb3b6163ae9d71725cd600a61112cfa1

==> Standard Output of failed command:


==> Standard Error of failed command:
gpg: failed to create temporary file '/Users/commitay/.gnupg/.#lk0x00007ff696c06d80.commitays-Mac.local.3137': No such file or directory
gpg: connecting dirmngr at '/Users/commitay/.gnupg/S.dirmngr' failed: No such file or directory
gpg: keyserver receive failed: No dirmngr

@reitermarkus
Copy link
Member Author

GPG has to be somehow initialized, I added gpg --list-keys, which initializes ~/.gnupg if it isn't yet.

end
homebrew_keyring_args = ["--no-default-keyring", "--keyring", homebrew_keyring_path]

# Ensure GPG intallation is initialized.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

@commitay
Copy link
Contributor

Does the embedded gpg verification need to be updated to use the gnupg formula rather than looking in HOMEBREW_PREFIX/bin for gpg?

@reitermarkus reitermarkus force-pushed the gpg-verification branch 2 times, most recently from d65c16f to e9a670c Compare May 11, 2018 11:53
@commitay
Copy link
Contributor

Having gnupg installed doesn't necessarily mean that a user will be able complete the verification (e.g. can't connect to the keyserver), we may want to provide a way to disable this check?

@reitermarkus
Copy link
Member Author

Let's do that if it actually becomes an issue.

@reitermarkus reitermarkus requested a review from claui June 14, 2018 18:40
@claui
Copy link
Contributor

claui commented Jun 29, 2018

Just as a heads up: I probably won’t get around to reviewing this until July 8.
I’m eager to get this merged though; I’ll definitely have a look at it.

@MikeMcQuaid
Copy link
Member

@reitermarkus What's the latest here?

@reitermarkus
Copy link
Member Author

Waiting on a review from @claui since she seems to know some things about GPG.

@claui
Copy link
Contributor

claui commented Jul 22, 2018

A number of issues I see with the approach that is proposed here (and already partially implemented before this PR):

  • Users are going to be confused as to what the GPG check tries to accomplish: just package integrity (does my file consist of the same bits as the file on the server)? Or package authenticity?

  • Let’s say a number of users will assume/expect that we’re dealing with some kind of authenticity check here. In my opinion, this expectation is not unreasonable from the user’s point of view: firstly, no one would expect the average Mac user to understand GnuPG well enough to get their expectations precisely right; and secondly, you know, GnuPG is that thing computer people use for privacy and security all the time – so it must be good, right? As soon as if we start using GnuPG, the user can (and will) expect at least some degree of package authenticity. But what would a maintainer have to do to live up to this expectation?

  • We could do something similar to what we already do with the SHA integrity check: look at the server’s domain, make an educated guess as to whether the domain is legit or “official”, and then calculate/compare the SHAs. Maybe we’d figure out a similar process for the GnuPG world, a process which gives similar guarantees to what the SHA check does. But even if we did, we’d still have only integrity checks and not authenticity. It would be just another variant of what we already have.

  • For authenticity, we’d have to tie a key ID to a real-life person or entity, and then assign at least some level of trust to that person/entity. Maybe there’s a way for a maintainer to do this but this needs to be discussed thoroughly; I haven’t come up with an idea yet that is reasonably secure while keeping the whole thing manageable for maintainers and users at the same time.
    There may be a number of pretty obvious cases, e. g. an extremely reputable vendor like AgileBits (1Password), whose PGP keys have been published widely. But that would still mean we’d introduce some trust metric for vendors (something Homebrew has never done), and we’d have to draw a line somewhere, and I have no idea what this would even mean in practice. Even if we decided to leave trust to the user (which would pose an UX nightmare in itself) and only deal with key ID vetting, maintainers would still have to come up with a manageable method for keeping track of “official” keys.
    I’ve closely followed the latest events around the eslint hack, as well as most of the discussion on package integrity at That Other Package Manager. That discussion has been going on for more than three years now, with nothing close to an acceptable solution on the horizon.

With all that in mind, I tend to lean towards what @vitorgalvao said in Homebrew/homebrew-cask#48862 (comment) on the topic of package authenticity:

It’s impossible for us to know when an app was tampered with and we need to set expectations accordingly.

In fact, I like this quote a lot because it basically summarizes all of node-forward/discussions#29.

So my suggestion would be to put this PR on hold, at least until someone comes up with an acceptable solution to the package authentication problem, UX-wise.

But that’s only my two cents. Maybe I’m entirely wrong, and there’s a reasonably good compromise hidden somewhere that I’ve missed. Thoughts/opinions?

@MikeMcQuaid
Copy link
Member

@claui Good points. Personally I think GPG is only a good solution for things like this if users are going to manage what they trust and what they don't explicitly. I don't think that really works when the granularity is per-package.

That discussion has been going on for more than three years now, with nothing close to an acceptable solution on the horizon.

For formula: between using SHA-256 package checksums, requiring 2FA for anyone who can merge commits and a CDN that doesn't allow republishing old packages: I think that's as good as you can get. Personally I think SHA256 for Casks is as good as you're going to get in terms of a balance between security and usability (and even then they may need disabled by default on some casks where there's an unversioned upstream tarball but you could make it easier for users to submit a PR to update this).

@ilovezfs
Copy link
Contributor

and even then they may need disabled by default on some casks where there's an unversioned upstream tarball but you could make it easier for users to submit a PR to update this

or the artifact could be mirrored to a CDN with a versioned url

@vitorgalvao
Copy link
Member

I think SHA256 for Casks is as good as you're going to get in terms of a balance between security and usability

Regarding casks, I see SHA256 (and this has been my view for as long as I can remember) as being a feature that provides an integrity check after a download, not a security feature.

Relying on SHA256 for security (for casks) is ineffective and takes a huge toll on usability, due to the amount of legitimate in-place changes developers make upstream. Users and contributors alike are understandably frustrated at the process of verifying SHA-only changes that can make casks unusable for weeks.

Homebrew/homebrew-cask#48862 (comment) already makes all these points. In my view, the best we’re going to get for casks is to get a way to quarantine downloads (efforts already in progress) and let macOS’ security model take over.

@MikeMcQuaid
Copy link
Member

we’re going to get for casks is to get a way to quarantine downloads (efforts already in progress) and let macOS’ security model take over.

👍

@reitermarkus
Copy link
Member Author

Then I'd say let's remove GPG support completely.

@reitermarkus reitermarkus mentioned this pull request Jul 22, 2018
6 tasks
@reitermarkus reitermarkus removed the in progress Maintainers are working on this label Jul 22, 2018
@stale
Copy link

stale bot commented Aug 12, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the stale No recent activity label Aug 12, 2018
@stale stale bot closed this Aug 19, 2018
@reitermarkus reitermarkus mentioned this pull request Aug 27, 2018
6 tasks
@lock lock bot added the outdated PR was locked due to age label Sep 18, 2018
@lock lock bot locked as resolved and limited conversation to collaborators Sep 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cask Homebrew Cask outdated PR was locked due to age stale No recent activity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants