Package owner identity and trust

Topics: Ecosystem, General
Apr 3, 2013 at 11:15 AM
Edited Apr 3, 2013 at 11:17 AM
I feel there is a need for being able to confirm the identity of package owners on nuget.org.

Currently:
  • Anybody can push a nuget package and claim he is the owner of the project (Many are like this. Antlr, bcrypt, ....)
  • The package contains binaries which can contain custom code. (No verification of the content is done on nuget.org)
  • There is no forced strong naming/signing in place. (And no way to filter packages based on this.)
  • Nobody is checking what the Powershell scripts are doing at install time. (Grab my outlook address book and upload it to some server?)
  • There is no (visible and documented) option to just "download" a nuget package so you can inspect the content. (I use v1 api url for that at the moment).
The result is that to "vet" a nuget package for our internal feed I need to:
If I don't do these steps there is no way I can trust the packages in our software.

It would be very appreciated if the following features could be considered:
  • The ability to sign packages
  • Display this signature can be displayed in the NuGet Clients and NuGet gallery feed
  • Allow filtering on "Signed" flag in the nuget feed
  • Allow registering the public keys in a "trusted publishers" list in the client tools
Note: I am willing to work on these features if they are considered relevant.
Apr 3, 2013 at 8:19 PM
I would love to work on this with you. I have some fun ideas fermenting with allowing either PGP signed packages and/or certificate based signing. I an thinking of good ways of supporting both simultaneously as the open source part of me likes the idea of PGP signing similar to how you can sign Ruby Gems and this can also provide authentication by referencing the public key in the originating public repository.

I think that code signing should also be implemented for the more corporate consumer.

As soon as I have some spare time (in about a week or two) I was going to start writing up a proposal. I'd love to collaborate with you.
Developer
Apr 3, 2013 at 10:13 PM
Please read our stance on this matter via Phil's blog post: http://haacked.com/archive/2013/02/19/trust-and-nuget.aspx
Apr 3, 2013 at 11:25 PM
I have read Phil's article and I still believe that package signing is a useful addition to NuGet. Accountability is still a requirement in many environments and I believe that there is definite value to being able to verify the source of a particular package.

I am not advocating requiring signed packages for NuGet.org but I think if Filip and myself (as well as any others) would find value in a package verification implementation and if we are willing to put in the work to do it that the idea should be taken into consideration.

One idea I like is by using PGP signing we can implement a distributed signing/revocation infrastructure that will allow packages to be verified as authentic in a few different ways.

The cheapest way is if the owner of the source code is also the NuGet package maintainer. They could put their public key in a well known location in their public source code repository. Just as many of us have standardized on a readme.md file in the root of our project source that GitHub nicely renders for us on our project page we could have a file containing the public PGP key whose private key was used to sign the package. Then all the client has to do is verify that the signature is valid and we can trust that the package was created by the entity who controls that repository. Revocation is also fairly easy in this scenario as well, the owner can generate a new key pair and once the new public key is posted all previous packages are no longer valid.

Another more sophisticated option is to piggyback on the Ruby Gems OpenPGP Certificate Authority https://www.rubygems-openpgp-ca.org/ . This is a signing framework we can build on and it is still at the clients discretion to trust that CAs keys or not. This organization also provides for key revocation. I have not spoken to them yet about piggybacking on their service but even if they are not willing to sign NuGet keys a similar infrastructure could be built.

If the source owner and the package maintainer are different entities then they have an option of coming to an agreement and the package maintainer could submit their public key in a pull request and thus the source maintainer just has to accept that public key as the "official" key that will sign that products NuGet packages.

We can also support multiple scenarios for package signing using certificates. Similar to my PGP option #1, a developer could generate a self signed certificate and publish the public key to their repository. Signature validation could be performed against the repository and a similar method of revocation (generate a new cert and replace the key in the repository) is supported.

For organizations or products that would like a more formalized identity validation/revocation there is the existing Certificate Authority infrastructure in place. Using the existing standard code signing certificates builds on long established libraries for signature validation that are supported on every platform.

Transitive trust is always a concern, but again, I would like to see package signing at least supported in the spec because then, just as with the decision to require signed packages, the trust details are at the consumers discretion. Right now as a NuGet user I have no choice.

Without supporting package signing the argument that "nobody would sign packages anyhow" is fallacious as there is no opportunity to implement signed packages without the functionality being at least theoretically available.
Apr 4, 2013 at 1:54 PM
I read Phil his post and i see nothing in there which contradicts with my feature request.

As a side matter. When a compromised Package is found, there is no mechanism to "blacklist" the package (not that I know at least). So anybody that has the package installed will keep it installed and will not know that the package he is using was compromised.
Apr 4, 2013 at 6:25 PM
I've been putting off talking about this for a while, but it's starting to bubble up more, so I'm writing a blog post that may help.

Gimme a couple of hours, and I'll post it.

G
Apr 4, 2013 at 10:06 PM
Dammit, blogging takes too much damn time...

See my post http://j.mp/Z4Vey8 in where I have a slightly different opinion than @haacked
Apr 5, 2013 at 12:44 AM
Edited Apr 5, 2013 at 12:44 AM
I would love to get rid of the need to review powershell scripts

(to address these steps
•Download the nuget package via
•Unzip the package content
•Review the included powershell scripts)

Do you think it would be helpful if in the gallery/search results we flagged packages that include powershell scripts, so that you would know which packages don't need that review step? (I don't know, but I would guess well under 50% of packages use powershell scripts currently).
Tim
Apr 5, 2013 at 2:31 AM
@fearthecowboy I like your blog post and I am curious to get your feedback on one of my proposals from above: publishing either a PGP or X509 public key in a canonical place in a repository and verifying the package signature against that?

The cacert.org idea is interesting as well.

So, wanna work with me and @Filip on this project? :)
Apr 5, 2013 at 4:36 PM
@jkuemerle -- PGP is really a non starter. It would be starting from nearly zero infrastructure (for how packages are signed etc,) whereas X.509 certificates are nearly perfect for the purpose, given that the OPC spec (the zip-file-based container that .nupkg is based on) already supports digital signatures (with a xml-dsig ).

With X.509 Ceritificate-based digital signatures, there's no need to store the public key in a known location, that's why we have Root certificates, which is the cryptographic method of asserting the facts in the certificate (IE, that the subject is who they say they are, because the certificate was signed by someone who is validating that)

With CACert.org , individuals can find people in their local area and get physically validated, which enables them to generate a code signing certificate to serve exactly the same purpose.

The CoApp project has a powershell cmdlet that can sign nearly everything (and we're adding xml-dsig in the next week or two)-- which will make it trivial to start signing packages ... and the cmdlet ships in the same module as the tool we're building to create Native (C/C++) packages for NuGet.
Apr 5, 2013 at 6:39 PM
Edited Apr 5, 2013 at 6:41 PM
When I initially thought about, this, I was thinking package signing doesn't help. But when I break down scenarios where package signing potentially saves me grief (assuming I know the signing key of a trusted identity - currently I never know this)

They are:
1) Someone has uploaded a fraudulent package on a lookalike account which I can easily confuse with the real package
or
2) Someone has compromised a real package owner's account, and uploaded a malilicious package in place of the real package
or
3) Someone has hacked nuget Gallery, and modified their nupkgs
or
4) Someone has man-in-the-middled the package upload or download
or
5) Some package owner was not worthy of the trust I bestowed in him

Solving #1 is ideally a problem for the gallery crew to a) detect package spam, and lookalike packages, or perhaps b) somehow detect packages with trojans
Solving #2 is a problem for package owners to keep their ownership secure - use strong passwords, don't share passwords, don't send random untrustworthy people package owner invites, and also for the gallery crew to handle credentials securely
Solving #3 is ideally a problem for the gallery crew to worry about, but if you are properly paranoid, you will be worried too!
Solving #4 should be preventable by you ensuring that you use SSL for package downloads - we are already enforcing it for package uploads.
Solving #5 is a problem for you to worry about on your sleepless nights. Signing doesn't help.

Reconsidering my initial opinion:
-Signing helps mitigate some of the threats, especially the owner account or nuget.org being compromised.
-It only helps mitigate those threats if the source of signing data is your trusted package owner directly, NOT via nuget.org, as if nuget.org is compromised or the owner's account is compromised and signatures are changed on nuget.org as a result, signing is useless
-NuGet tools could help you establish trust by declaring a standard a way for you to easily verify package signatures by pasting in some kind of public key obtained from e.g. your favorite project's homepage
-You could instead get a a lot of proof the package has not been tampered with also just from being able to declare a package file's SHA256 hash with an official one posted by the package owner again on a non-nuget.org source.

My conclusion:
We could go with signing or hashing, but for best security they will need to work in a way which is independent of nuget.org.
Package owners would opt in to posting their official nupkg package hashes or signatures on their well-known-and-trusted-by-you project homepage, and a prompt during package download that allows you to 'paste and verify hash/signature from project home page'

Signing is better in this way:
1) the package owner can have a single public key used for signing all their packages, and all versions of those, reducing the number of times you have to cross-check the public key.
2) if the package owner's site is compromised the attacker doesn't have the key

Hashing is better in this way:
You don't need to worry about key management, trust chains (yuck)
Apr 5, 2013 at 8:08 PM
tilovell wrote:
Hashing is better in this way:
You don't need to worry about key management, trust chains (yuck)
You really don't need to worry much about key management with Certificates, it's all handled by the tools anyway.

And simple hashing wouldn't help if the posted hash is compromised too.
Apr 5, 2013 at 8:44 PM
I believe signing is a good solution but the tooling needs to be such that it is not a hassle (or most developers won't use it which defeats the purpose).

On the client side it must be extremely easy to separate signed from unsigned packages and users should be able to add "trusted" publishers. (It would be great if nuget.org could manage some sort of "trusted publishers" list for the most commonly used packages.)
Apr 5, 2013 at 9:22 PM
fearthecowboy wrote:
With X.509 Ceritificate-based digital signatures, there's no need to store the public key in a known location, that's why we have Root certificates, which is the cryptographic method of asserting the facts in the certificate (IE, that the subject is who they say they are, because the certificate was signed by someone who is validating that)

With CACert.org , individuals can find people in their local area and get physically validated, which enables them to generate a code signing certificate to serve exactly the same purpose.
I think that having the option of storing the public key in a canonical location and validating with that also provides value. It means that I as a developer (who may live in a remote area) do not have to go out into the real world and find someone with enough points at CACert.org or sign my CSR.
The CoApp project has a powershell cmdlet that can sign nearly everything (and we're adding xml-dsig in the next week or two)-- which will make it trivial to start signing packages ... and the cmdlet ships in the same module as the tool we're building to create Native (C/C++) packages for NuGet.
That is awesome because the only other zip signing tool I have been able to find is a JAR that is primarily used to sign APKs and I try not to have Java on my ecurity sensitive systems :)
Apr 5, 2013 at 9:35 PM
Even without using CACert.org , X.509 Certs still give you what you want.

It's a perfectly valid scenario that you could generate a self-signed certificate -- which has exactly the same effect as you generating a keypair on your own and uploading it somewhere... consumers really have no way of validating you any more with a mysteriously generated and uploaded generic keypair than a self-signed certificate anyway.

This way, we can streamline the whole operation down to a single scenario -- always sign your package, and do so with a cert that pretty much falls into one of three categories:
  1. A certificate issued by a Trusted Root CA -- organizations can use that to give the consumer a higher level of confidence that the publisher is who they say they are
  2. A certificate issued by a "Known, non-Trusted-Root CA" -- (eg, CACert.org) individuals can use that to give the consumer a moderate level of confidence that the publisher is who they say they are -- with a well-documented and transparent model for determining Assurance.
  3. A self-signed certificate -- At least you know that updates are coming from the same person, regardless of how well you can establish their identity.
And, really, your upload-your-id somewhere idea can still be done with people publishing their certificate in a known method -- ie, embedding it as a reference in their blog or something...

If we go down the path of a single, consistent signature model, it's much easier to add on an appropriate Trust/Reputation UI when the time comes.
Apr 5, 2013 at 9:47 PM
FilipDeVos wrote:
I believe signing is a good solution but the tooling needs to be such that it is not a hassle (or most developers won't use it which defeats the purpose).
Indeed, which is precisely why I wrote my own Code-signing tool that doesn't suck eggs like 'signtool' or that stack of crap that java uses. CoApp's codesigning is so damn simple (as it should have been all along), it completely trivializes the act of signing.
PS C: >Set-CodeSignature myfile.exe -Certificate Cert:\CurrentUser\My\<thumbprint> 
On the client side it must be extremely easy to separate signed from unsigned packages and users should be able to add "trusted" publishers. (It would be great if nuget.org could manage some sort of "trusted publishers" list for the most commonly used packages.)
So... the trouble is, your criteria of a 'trusted publisher' could differ from someone else's. Outside of :
  • Issued from a Trusted Root,
  • Issued from a Known Root
  • Issued from a non-known-root
there isn't really a way to easily distinguish any real arbitrary level of trust.

But the UI could certainly give you the relevant information in an appropriate way for you to make the distinction past that.