python-poetry / poetry

Python packaging and dependency management made easy
https://python-poetry.org
MIT License
31.75k stars 2.27k forks source link

Provide signature for poetry installation script #3442

Closed macgeneral closed 2 years ago

macgeneral commented 3 years ago

Feature Request

Related: Issue #127

I think the current preferred way of installing poetry is relative insecure. Piping a script directly from curl or wget to python or the shell is always a risk in case someone manages to modify the file on the server (even if it is a multi-factor secured Github repository). While signatures still require that you trust the key in the first place, they can help detect files that were tampered on the server.

Of course experienced users can download the file first and inspect it afterwards before running it with python (if he or she knows what to look for and if that file doesn't consist of hundreds or thousands of lines like in get-poetry.py's case), but this does not work for automated installs in a headless (e.g. Docker) environment and can be very time consuming.

Therefore I suggest to sign the get-poetry.py file with a separate gpg key of which the public key is stored on your website. Then users can at least verify that it was a developer they (have to) trust who released this version.

dev@vm:~$ gpg --full-gen-key
dev@vm:~$ gpg --list-secret-keys --keyid-format LONG
dev@vm:~$ gpg --export [KEYID] > poetry_pub.gpg

When committing a new version to Github developers have to (automatically) sign it first

dev@vm:~$ gpg --local-user [KEYID] --detach-sign get-poetry.py

Users now have the possibility to verify the file integrity with

user@pc:~$ curl -fsO https://python-poetry.org/poetry_pub.gpg
user@pc:~$ curl -fsO https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py
user@pc:~$ curl -fsO https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py.sig
user@pc:~$ gpg --no-default-keyring --keyring poetry_pub.gpg --verify get-poetry.py.sig
user@pc:~$ python get-poetry.py

and integrate it in their Dockerfile like this:

WORKDIR /tmp
RUN curl -fsO https://python-poetry.org/poetry_pub.gpg
# verify poetry public key's SHA256 hashsum - the pipeline will fail if the key doesn't match
RUN echo "sha256sum_of_poetry_pub.gpg  poetry_pub.gpg" > poetry_pub.sha256
RUN sha256sum -c poetry_pub.sha256
# get the install script and signature
RUN curl -fsO https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py
RUN curl -fsO https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py.sig
# verify the get-poetry.py file
RUN gpg --no-default-keyring --keyring poetry_pub.gpg --verify get-poetry.py.sig
# install poetry
RUN python get-poetry.py

I know this doesn't prevent all possible attacks, but especially if I can hard code the sha256sum of your key file into my Dockerfile I can be sure that the key wasn't exchanged as well. Docker runs all commands as root by default, so installing poetry right now in your suggested way requires a lot of trust / precautions if there's no distribution managed version of it.

Note: I'm using the binary gpg format in this case because when using the ASCII armored version (--armor/-a) you can't use it as keyring without converting it back first. This is just an example anyways - of course you could also upload the key to a keyserver and make the user install it in his/her truststore. I prefer the separate from trust store way because then I don't have to globally trust the key.

Edit: Of course this only makes sense if the key is password protected and the file is signed on the developers machine and not automatically in a Github pipeline (in case someone manages to obtain a repository API token etc.).

macgeneral commented 3 years ago

As a small follow up why I think this is important/relevant:

and there are probably many more examples (those were just the ones that instantly came to my mind).

Edit: Currently there's no way of knowing if get-poetry.py is legitimate or not. I have to trust the maintainers/developers to use multi-factor authentication, secure passwords managed by a secure password manager (not password123 etc.), watch over their API tokens, make sure they don't install hacked dependencies on accident themselves etc. pp.

There are a lot of potential ways an attacker could obtain commit access to this repository:

The number of people/companies I have to trust grows exponentially for an unsigned file. With a signed version I only have to trust the developers and maintainers of this great project.

Potential damage is up to imagination as well:

And even a time slot of a few hours of being undetected might be enough to cause lot's of potential damage.

macgeneral commented 3 years ago

Just a small update with a recent case which uses a similar install procedure:

tarkatronic commented 3 years ago

I'd just like to add on here in the hopes that this ticket can get some attention. While the practice of curl | bash has never been a great one security-wise, I believe that the Codecov compromise has brought this issues far more to light. What this means for poetry is that this may soon (if it has not already) become a hard blocker for people wanting to use the tool. I fear that this may become a restriction from my employer, and from others as well, as we look to follow more secure practices in our work. And the last thing I want to have to do is go back to setuptools.

abn commented 2 years ago

Would be great if someone can look into getting the script signed via https://www.sigstore.dev/ in our ci and the signature uploaded somewhere. This needs to happen in https://github.com/python-poetry/install.python-poetry.org.

github-actions[bot] commented 8 months ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.