pypa / pip-audit

Audits Python environments, requirements files and dependency trees for known security vulnerabilities, and can automatically fix them
https://pypi.org/project/pip-audit/
Apache License 2.0
942 stars 62 forks source link

PermissionError: [Errno 13] Permission denied: '/tmp/tmpzrluurcb/bin/python3' #732

Closed rdinoff closed 4 months ago

rdinoff commented 4 months ago

Bug description

if /tmp/ is mounted with noexec you get the following stack trace.

Expected behavior

need an option to put tmp files in a different location

(venv) rdinoff@audit:~/audit$ pip-audit -r requirements.txt
Traceback (most recent call last):
  File "/home/rdinoff/audit/venv/bin/pip-audit", line 8, in <module>
    sys.exit(audit())
  File "/home/rdinoff/audit/venv/lib/python3.9/site-packages/pip_audit/_cli.py", line 509, in audit
    for spec, vulns in auditor.audit(source):
  File "/home/rdinoff/audit/venv/lib/python3.9/site-packages/pip_audit/_audit.py", line 67, in audit
    for dep, vulns in self._service.query_all(specs):
  File "/home/rdinoff/audit/venv/lib/python3.9/site-packages/pip_audit/_service/interface.py", line 154, in query_all
    for spec in specs:
  File "/home/rdinoff/audit/venv/lib/python3.9/site-packages/pip_audit/_dependency_source/requirement.py", line 134, in collect
    yield from self._collect_from_files(collect_files)
  File "/home/rdinoff/audit/venv/lib/python3.9/site-packages/pip_audit/_dependency_source/requirement.py", line 180, in _collect_from_files
    ve.create(ve_dir)
  File "/usr/lib/python3.9/venv/__init__.py", line 75, in create
    self._setup_pip(context)
  File "/usr/lib/python3.9/venv/__init__.py", line 313, in _setup_pip
    subprocess.check_output(cmd, stderr=subprocess.STDOUT)
  File "/usr/lib/python3.9/subprocess.py", line 424, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/usr/lib/python3.9/subprocess.py", line 505, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/lib/python3.9/subprocess.py", line 951, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/lib/python3.9/subprocess.py", line 1837, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
PermissionError: [Errno 13] Permission denied: '/tmp/tmpzrluurcb/bin/python3'

Platform information

woodruffw commented 4 months ago

Thanks for the report! Summarizing to make sure my understanding is correct:

  1. You have /tmp mounted as noexec
  2. You ran pip-audit in requirements mode (pip-audit -r ...)
  3. pip-audit failed because it couldn't run a python3 shim from within a venv that was created within /tmp

This is an eventuality we hadn't considered 🙂 -- did you manually configure your fstab on Ubuntu 22.04? As far as I know, this isn't the default.

(We'll need to think about how/if we want to handle this -- there are myriad ways for users to trip up userspace programs with filesystem options.)

rdinoff commented 4 months ago

Your understanding is correct. This happened on a Ubuntu VM image that was "improved" for security reasons.

woodruffw commented 4 months ago

Thanks for confirming! Out of curiosity: where did that VM image come from, if you can say?

(Also: could you check to see if /var/tmp allows +x? That may be a better choice for us here.)

woodruffw commented 4 months ago

I asked around about this, and TIL that noexec on /tmp is a somewhat common configuration recommendation, if not necessarily commonly deployed:

(many thanks to @jayofdoom for pointing this out!)

Given that, I think pip-audit can do a better job of surfacing the state here. My current idea: we'll try and detect if the default tmpdir is noexec and render an intelligible error, rather than failing well into the audit process.

Longer term, we could probably try a shortlist of temporary directories to find one that allows +x, and/or improve the documentation to make it clear that the user will have to pass a different tmpdir or reconfigure their tmpdir.

How does that sound @rdinoff?

rdinoff commented 4 months ago

/var/tmp does allow +x (not mounted with noexec)

woodruffw commented 4 months ago

Forgot to mention: as a temporary workaround, TMPDIR=/var/tmp pip-audit -r requirememts.txt should work, since Python's tempfile module will use that variable to determine the temporary directory prefix to use.

di commented 4 months ago

Since the error here isn't from our own code, I think we should just fail gracefully (rather than raise an exception) and hint that the user should set TMPDIR.

woodruffw commented 4 months ago

Since the error here isn't from our own code, I think we should just fail gracefully (rather than raise an exception) and hint that the user should set TMPDIR.

SGTM! That's what #737 will end up doing, once I write a (mocked) test.

woodruffw commented 4 months ago

We've included an improved error message for this in 2.7.1. Thank you again for reporting @rdinoff!

rdinoff commented 4 months ago

fix looks good ....

(venv) rdinoff:~/audit$ pip-audit -r requirements.txt
ERROR:pip_audit._cli:Couldn't execute in a temporary directory under /tmp. This is sometimes caused by a noexec mount flag or other setting. Consider changing this setting or explicitly specifying a different temporary directory via the TMPDIR environment variable.
(venv) rdinoff:~/aydit$ echo $?
1
(venv) rdinoff:~/audit$ TMPDIR=/var/tmp pip-audit -r requirements.txt
No known vulnerabilities found