Open KOLANICH opened 2 years ago
Running pip as root is not supported in any case, so you simply shouldn't do this (or if you do, you should be aware of, and deal with, the consequences yourself). From your description, it sounds like you are at least aware of the risks, so that is good. But pip won't address these risks for you, that's something you have to handle yourself (ideally by not running sudo pip
in the first place...)
I think solving the problem should be straightforward now that there are isolated builds running in subprocesses.
A demonstration - in an otherwise empty directory:
$ cat > setup.py
import os
raise ValueError(os.geteuid())
$ python -m venv test_venv
$ sudo test_venv/bin/pip install -e .
Obtaining file:///...
Preparing metadata (setup.py) ... error
error: subprocess-exited-with-error
× python setup.py egg_info did not run successfully.
│ exit code: 1
╰─> [6 lines of output]
Traceback (most recent call last):
File "<string>", line 2, in <module>
File "<pip-setuptools-caller>", line 34, in <module>
File "/path/to/setup.py", line 3, in <module>
raise ValueError(os.geteuid())
ValueError: 0
[end of output]
(Etc.) All that should be necessary is:
os.seteuid()
(or the main process should temporarily do so before spawning) to run as the original user (int(os.environ[SUDO_UID])
) or as nobody
before setup.py
is invoked.os.setgroups([])
- ref. https://stackoverflow.com/questions/2699907).Allowing the build process to run as root increases the attack surface area: malware (whether typo-squatted, supply-chain-attacked etc.) now gets to do its work with admin privileges automatically at install time, before the local source can be inspected. Dropping rights for wheel building is a useful mitigation: even if malware were installed globally by sudo pip
, if the install process only has user rights, it can't harm the system until the installed package is actually used. It also represents defense-in-depth in case Setuptools, or another popular build system, gets compromised.
Telling people "running pip as root is not supported" ignores the huge volume of bad authoritative advice already out there as described in https://github.com/pypa/pip/issues/7802#issuecomment-593698570 ). It also ignores the fact that Pipx explicitly supports global installation with the --global
flag now (as discussed in #12651), which of course requires sudo rights, which will of course be passed on to Pip (so that it can unpack files in a root-owned directory).
Using --only-binary=:all:
is an incomplete workaround; sometimes wheels do need to be built. (Especially as long as "editable wheels" are the primary model for editable installs.)
It's also possible, I suppose, to install in a user venv, manually fix all the paths in the venv according to what they'll need to be, and then sudo mv
it to an appropriate location. But this is complex enough to justify automation already. Installation into an existing global venv (like with pipx inject
) or (for those who really live dangerously) the system Python would be even more awkward.
What's the problem this feature will solve?
Building a wheel results in execution of a lot of potentially vulnerable or untrustworthy code:
setup.py
attr:
insetup.cfg
andtool.setuptools.dynamic
section (it is planned to be fixed somewhen in sallow only statically parsed stuff by default).setuptools
plugins.There is usually no reason to call all these from a privileged user. But some packages are still available on
pypi
as sdists only, so users installing them withsudo pip
result in them being fetched and built from root. I personally have disabled fetching anything from pypi, BTW.The most severe issue for me is editable install. It is extremily inconvenient to rebuild wheels and reinstall them after every minorest change when developing python code that must be run from root. I know it introduces local privilege escalation, but TBH if one runs untrustworthy code on own machine, he is already deeply in danger.
The issue got more severe today because of https://github.com/pypa/setuptools_scm/issues/707 .
setuptools_scm
is a tool to get version from git tags, it callsgit
for that. Butpip
runs wheel building from root, while the source dir is usually owned by the user initiating the build. The recent fix in git to eliminate such vulnerabilities checks that the user runninggit
is the same as the user owning the repo. Of coursefakeroot
is the workaround, but I think a more correct solution is needed.Describe the solution you'd like
sudo
root
Alternative Solutions
No.
Additional context
7802
Code of Conduct