pyproject.toml build backends
During pip install from source (build isolation phase)
- Lives in
pyproject.toml [build-system] table- Attacker needs
- Supply-chain foothold
- Lifecycle
- InstallStartupyour codeModule loadRuntimeREPL
Runs while dependencies download and build. The app has never started.
How it runs
The "modern" replacement for setup.py is pyproject.toml with a build backend. The goal was declarative builds that run less arbitrary Python. It sort of works.
[build-system]
requires = ["setuptools", "my-evil-build-plugin"]
build-backend = "setuptools.build_meta"
pip installs the requires list into an isolated build environment, and each of those packages can have its own setup.py. The build backend itself runs arbitrary Python to produce the wheel. So execution moves from one obvious setup.py to a chain of build dependencies that each get installed and executed. That chain is harder to audit.
Custom backends go further. Point build-backend at any Python module and pip will call its build_wheel() / build_sdist() functions. That's arbitrary code execution with a fancier hat.
Defend
Audit build-system.requires like any dependency; pin and hash build deps; prefer prebuilt wheels to skip the backend entirely.