When you pip install foo
, you are getting the latest and greatest version of foo
and all its dependencies.
However, foo
's behavior (or that of its dependencies) may change over time. This introduces unexpected breakage into your CI pipeline,
usually exactly at the time when you don't want it.
When you pip install foo
in your CI pipeline, you trust
- PyPI,
- the authors of
foo
, and - all authors of all (sub)dependencies of
foo
to not be compromised. If one of them is, an attacker may push a malicious package to PyPI which steals your code
and your repository secrets (e.g. deployment tokens).1
To mitigate this problem, you should pin your dependencies, i.e. use a requirements.txt
/poetry.lock
/... lock file
that ensures only specific versions (with specific file hashes) are allowed. This changes the threat model from "trust
continuously" to "trust on first use".
The actions provided here allow you to securely (i.e. with pinning + hashes) install popular tools to use in your CI pipeline without any additional lock files.
For example, you maybe want to run black in your CI pipeline, but black is not a dependency for your application. Instead of adding a separate lock file to your repository, you just use the install-pinned/black action.
By pinning your tools, the dependency graph becomes static. This means that you will not automatically get new (security) updates. To mitigate this, you can set up Dependabot so that your pins are updated regularly.
- autoflake
- black
- build
- codecov-cli
- isort
- maturin
- maturin[zig]
- mitmproxy
- mypy
- pdm
- pdm-backend
- pdoc
- pip-tools
- poetry
- pytest
- pyupgrade
- reorder_python_imports
- ruff
- setuptools
- tox
- tox-uv
- twine
- uv
- wheel
- yesqa
Your tool is not on the list? Request it here.
If you believe you've identified a security issue with install-pinned, please report it to @mhils using the email address listed on his GitHub profile.
Footnotes
-
This typically includes GitHub secrets that are not available to the current workflow. By default,
GITHUB_TOKEN
can push new commits, which can be used to rewrite workflows and obtain more secrets. ↩