-
Notifications
You must be signed in to change notification settings - Fork 37
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
Verify integrity of downloaded esbuild package #42
Comments
that's the thing, unfortunately that doesn't seem to be the case, per @voltone:
|
It appears that PGP keys can be translated to PEM keys with just a few minor changes:
For example, a PGP key like this (the
Becomes this:
Indeed, after applying those transformations to https://keybase.io/npmregistry/pgp_keys.asc I was able to load the resulting PEM key using |
Hi @frerich, I would definitely love a PR that implements this. :) Perhaps we should even extract this as a package called About the npm url though, how useful would that be in practice? If there is a MITM attach, then the URL would also be changed. So I think we would need to have the pgp keys hardcoded into this repo, which is fine IMO. For the hashing, we could hardcode the hash for the versions we use by default but otherwise the user would have to list the hash? |
I think hardcoding (or requiring to list) hashes would be a plausible improvement. In fact, I originally meant to suggest that, too. However, I'd love to be able to get away without this and rather rely on the hashes available via the REST API. I just need to be careful to verify that these hashes can be trusted (i.e. they haven't been tampered with, too!). :-) It appears that the information which is relevant for making sure that we're not downloading something nasty is stored in the {
"integrity": "sha512-hMbT5YiBrFL763mnwR9BqNtq9XtJgJRxYs7Ad++KUd+ZhMoVE0Rs/YLe1oor9uBGhHLqQsZuJ2dUHjCsfT/iDg==",
"shasum": "644efb31fb27e291465e24757b3194d36aa2eb7d",
"tarball": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.0.tgz",
"fileCount": 3,
"unpackedSize": 8249070,
"npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhoT2OCRA9TVsSAnZWagAAhD0P/1lADzoSLVZMGgYuOJAH\n1WZ3bC54yl6Ixq8DzEck8GYRjJEHjuWVNcFb40HXl8utryLJfRRk0zdWqvLF\n2lc8oRufMc+fZkNBg3vOEOasLo0D+dcOy/2yDHIX4GSsdS+Le4UmgMXk7Ind\nVtUwPtDmpXr7VdQn96rCx3ZolrLCPJ94A2TsLIkTRnT6ThEAkWURiKeKGrDd\nCTPnJir9r18xdMiKbLimMpgdBe2P9n98EvY84quy1xBQGFfMA9YLwXJPR4dX\nvKRARJHvnfnY79RTR13VBbyiwVxiumA14MmHQGBLWxrorY//L8q3tWtiQ5by\nknpVsrDVgskd9cPkQuTA0gGtYIEUHWGyvd8nC3ZF1en3+DJanbRJV+4rhjdJ\nYRK5sN4mXLM6JO4FSrz/5lVN00LdaKTOMnB7S6gbuVCUydWMTDv7WgDE27ib\nSLpFVBco05oebszRvLk8xN3zgjgkQ6iBDvm7iBeotl4gcG/jet6GPoYHryxr\nXS5dCi3Q/U1HFTO2Fn5xmy6cTpyhw+B2hL0WrqtNm5Q3+zdD37W+02VnNsu7\nzOG+X07HqcSPqpQxHYjI2Q+kdAzeJq6wzzvzPUlMvydpObHP9qAwt3I1Rl6r\njUC3SsUjQkzwViUDLWXoFd0lMFOkFvzvgswdVlwfT1mV2sfggCvH44qFQokH\nqaO4\r\n=09zh\r\n-----END PGP SIGNATURE-----\r\n"
} It seems useful to not only consider the hashsum but also meta information such as the number of files or the uncompressed size (to guard against ZIP bombs). However, how can we verify that this JSON payload hasn't been tampered with, too? The instructions in the npm public registry docs explain that a string made from the package name, the package version and the
I suppose(!) that this is what people who (unlike me) actually know something about cryptography might call the 'message' to verify. This message is then meant to be verified given the signature in What I don't quite get is: how does verifying this message ensure that the other fields in the |
In my opinion it would be enough to just see if the archive wasn't tampered with, I don't think we need to check other pieces of data like number of files. If archive was signed and we can verify it with something like If this works it would be absolutely fantastic to use the same solution on tzdata! |
My understanding is that getting the hash from the same source as the package does not help with anything. So you either need to pass it on the side or, when you download it for the first time, you store the hash somewhere (assets/.esbuild.hash). Then you guarantee it wasn't tampered afterwards. But i agree with @wojtekmach, the most important is the PGP signing. If we can validate the signature, then we can trust the hash, and use it to validate the package. :) The public key is hardcoded then. |
A first shot at trying to use I massaged the official public key into a PEM file according to the instructions I mentioned above, which gets me this: https://gist.github.com/frerich/db9a325e393c10482ca99f5ab20c95fd Loading this PEM works (i.e. it appears to be syntactically valid), but decoding doesn't:
A quick Google query revealed a StackOverflow thread which might be related. It suggests that this might be a bug in OTP (I can't tell if this is true or not), but unfortunately I couldn't find any workaround. |
Both the public key and the signature use PGP-encoding according to RFC4880. As I said in the |
Thanks a lot for confirming @voltone! ❤️ I wonder what the path of least resistance would be here. Is it actually required to implement the RFC in Elixir or can we maybe leverage some existing implementation (even if it just means shelling out to a command line utility)? I'd be happy to do the grunt work to get this in, but I'm not terribly familiar with the state of cryptography libraries in Elixir so I'm hesitant to make the first move. 😊 Any thoughts on this would be much appreciated! |
Relying on external binaries is going to be very brittle. I can prepare some code that implements the most important parts of the RFC, but I'm not sure I can commit to maintaining it as a package: my track record as a package maintainer is not great, unfortunately. |
I think a proof of concept can be extremely helpful. You can leave it in a Gist or in an archived repo if you don’t want to maintain it. :) |
Stuck on the same error as @frerich, would love to see a solution or some movement on this issue. |
The package currently fetches a tarball from npmjs.com without verifying that the package has not been tampered with. Luckily, the npm public registry provides plenty of metadata for packages via its REST API, including a digital signature and a hashsum of the package. It seems like a good idea to make use of this information.
The chapter on Verifying the PGP signature of a package from the npm public registry explains how to go about doing that. Luckily, it doesn't seem to be a lot of effort:
https://registry.npmjs.org/esbuild-darwin-arm64/0.14.0
. The returned document contains (among other things) the effective URL from where to download the package as well as its hash sum, the uncompressed file size and a PGP key to verify the package description.I believe no extra dependency would be needed here (at least I hope that Erlang's
:public_key
and:crypto
can be used for everything related to integrity checking), except for a JSON parser.Does this seem like a worthwhile improvement? If so, I'd be happy to look into implementing this improvement!
The text was updated successfully, but these errors were encountered: