Skip to main content

pipvm

Like pipx, but each installed program runs in its own virtual machine (or other type of jail).

AI-generated and unreviewed.

Motivation

pip install runs arbitrary code, and the programs it installs run with everything your user can touch. pipx keeps their dependencies apart, but not the programs themselves. pipvm installs a package with pipx inside a small QEMU virtual machine, then starts a fresh machine every time you run it. The program sees a minimal Linux with no access to your files, your X server, your ssh agent or your network (unless you ask for the network).

Only the virtual machine "backend" exists so far; the code is arranged so that others (podman, for example) can be added later.

Alternatives and prior work

This is mostly a convenience wrapper around various tools (qemu, pipx, Xephyr) you could use these directly.

Sharing data can be a pain. For tigher interaction I made a tool called [ptrace-approve] which allows you to approve individual system calls - this might be more convenient in these use cases with the price of more configuration. If your use cases are simplare you can use this.

Caveats

The most annoying thing about these tools is sharing data and resources which often make VMs unusable. I am partly making this tool as a game to practice using VMs where I can "secure" things which have easy data requirements.

There is quiter a lot of overhead of running VMs.

Usage

pipvm install cowsay                    # builds a base image the first time, then installs with pipx in a VM
cowsay -t "hello"                       # a command like pipx's: each run starts a fresh VM; stdin, stdout, stderr and exit status are forwarded
pipvm run cowsay -- -t "hello"          # the same without the command on your PATH
echo hi | pipvm run --exe cat cowsay    # --exe: the program to run, when it is not named like the package
pipvm run --net httpie -- example.com   # let this run use the internet (it has none by default)
pipvm run --shell cowsay                # a shell in the VM, to look around
pipvm list
pipvm uninstall cowsay

Options for run go before the app's name; everything after -- is passed to the program.

install writes a small script for each command the package provides into ~/.local/bin (or $PIPVM_BIN_DIR), like pipx does. The script just runs pipvm run --exe COMMAND NAME -- "$@", so the command always runs in a VM. A file that is already there and is not pipvm's own script is never overwritten (pipvm says so, and you can still use pipvm run --exe). uninstall removes only the scripts pipvm wrote. Commands started this way have no network; to give one network access run it with pipvm run --net instead.

  • The program runs in the guest as an unprivileged user. QEMU itself runs as you, not root.
  • A new machine is started for every run, and everything the program writes to its disk is thrown away when it stops. Programs that need to keep state between runs cannot yet.
  • The guest has no network unless you pass --net: it cannot reach the internet, your LAN or your host.
  • Your files are not visible to it. Pass data through standard input and output.
  • install does have network access, to fetch the package.

How it works

  • The first install downloads Alpine's cloud image (checked against Alpine's published sha512) and runs a one-off VM that installs Python, pipx and ssh into it. The result is cached in ~/.cache/pipvm, and every app is a small copy-on-write overlay on top of it, so adding an app does not copy the base.
  • install boots the overlay with network access, runs pipx install as the unprivileged user, then powers the VM off cleanly so the package is on the disk.
  • run boots the overlay with QEMU's -snapshot (writes are discarded), waits for ssh on a port forwarded on localhost, and runs the program over ssh. The ssh streams are yours, so output arrives as the program writes it, with standard output and error kept apart.
  • Only a key pipvm generates (in ~/.cache/pipvm) can log into the guest.

In one test run on this machine, preparing the base image took 26 seconds (plus the download), and starting a VM and running cowsay took about 6 seconds.

Requirements

Linux with KVM available to your user, qemu-system-x86_64, qemu-img, xorriso, and ssh. x86_64 only. The first install needs the internet. debugfs (e2fsprogs), if present, is used to show the provisioning log if preparing the image fails.

Limits

  • A VM protects your machine from the program. It does not protect the internet from the program when --net is on.
  • Programs cannot yet read or write your files, or open windows: file sharing and display are not implemented.
  • QEMU and the Linux guest are themselves code that could have bugs; a VM is a stronger boundary than a container, not an absolute one.

Development

pipx install --editable .
python3 -m unittest discover -s tests

Metadata

Release files for pip-vm 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pip-vm 0.1.1
File Size Uploaded Provenance Actions
pip_vm-0.1.1.tar.gz 31.0 kB Without provenance Details for pip_vm-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pip-vm 0.1.1
File Interpreter ABI Platform Actions
pip_vm-0.1.1-py3-none-any.whl Python 3 none any Details for pip_vm-0.1.1-py3-none-any.whl

Total release size: 63.0 kB

Release files / pip_vm-0.1.1.tar.gz

Download URL pip_vm-0.1.1.tar.gz
Size 31.0 kB
Tags Source
SHA-256 checksum
How to use checksums
e044b537cf69109ce53ecf8b0935a4c0d2936dfff0feeee4e1f4d9b270a7138b
BLAKE2b-256 checksum
How to use checksums
28317bce547ddd35f3b80a9186de60c56a3d433764090ee3af8cff11393a5bdf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / pip_vm-0.1.1-py3-none-any.whl

Download URL pip_vm-0.1.1-py3-none-any.whl
Size 32.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4921a2ca76218fd3054031c43d189f0d556a7542b508cc1ac1e4a43fda7cfed8
BLAKE2b-256 checksum
How to use checksums
9108809e1cdbe0f3bec5cc7f8eee6e726a3fe5979e20358a7bb73d709d9f5399
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Security for pip-vm 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page