Skip to content

Pin the smoke workflow pip dependencies by hash - #451

Open
Garra1980 wants to merge 1 commit into
mainfrom
Garra1980/pin-pip-by-hash
Open

Garra1980 wants to merge 1 commit into
mainfrom
Garra1980/pin-pip-by-hash

Conversation

@Garra1980

Copy link
Copy Markdown
Contributor

Summary

The smoke workflow installed its build and lint tools with version pins only:

pip install cmake==4.4.4 nanobind==2.9 lit==23.1.3 \
  clang-format==23.1.3 cmake-format==0.6.13 ruff==0.17.1

The == pins cover the six direct dependencies, but not their transitive ones.
cmake-format requires cmakelang, which requires six, and both resolved to
whatever was newest on PyPI at the time of the run. A malicious release of either
would have executed in CI. The pinned direct versions hid that.

This also satisfies the OpenSSF Scorecard Pinned-Dependencies finding
pipCommand not pinned by hash for .github/workflows/smoke.yml:43.

Changes

  • Add .github/workflows/requirements.txt: the six tools plus the two
    transitive dependencies, each with a SHA-256 hash for every file of that
    release. The header documents how to regenerate it.
  • Install it with pip install --require-hashes --only-binary :all: -r ....

--require-hashes fails unless every requirement, including transitive ones, is
pinned and hashed. --only-binary stops pip from falling back to an sdist, whose
setup.py would otherwise run during the build.

No tool versions change. nanobind==2.9 is written as its exact release, 2.9.0.

Testing

Installed into a clean venv, which reports the intended versions:

pip install --require-hashes --only-binary :all: -r .github/workflows/requirements.txt
  cmake         cmake version 4.4.4
  lit           lit 23.1.3
  clang-format  clang-format version 23.1.3
  cmake-format  0.6.13
  ruff          ruff 0.17.1
  nanobind      importable

Checked that it fails closed: corrupting every hash of one entry aborts the
install with THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE
and exit status 1.

Every file pip selects is py3-none-any, py2.py3-none-any or
manylinux_x86_64. None carries a CPython tag, so the file keeps working if the
runner's Python version changes.

Notes for maintainers

  • Changing a version means regenerating its hashes, or the job fails. The header
    gives both commands.
  • .github/dependabot.yml currently watches pip only in /python, so it never
    tracked this list. That is why smoke.yml still pinned nanobind==2.9 while
    python/pyproject.toml had moved to 3.1.0. Adding a pip entry for
    /.github/workflows would let Dependabot keep this file current. Left out of
    this PR to keep it focused.
  • scripts/create-venv.sh carries the same Scorecard finding. It is not hash
    pinnable, because it installs torch-mlir dev wheels from a feed that moves.
    It is also not called by any workflow. Worth a separate look: it has no version
    pins at all, and its --extra-index-url gives no index priority, so the
    highest version across both indexes wins.

🤖 Generated with Claude Code

The workflow installed its build and lint tools with version pins only.
Transitive dependencies were not pinned at all: cmake-format pulls in
cmakelang, which pulls in six, and both floated to the latest release on
every run.

Move the list into .github/workflows/requirements.txt with a SHA-256 hash
for every release file, and install it with --require-hashes. Add
--only-binary to keep pip from falling back to an sdist, whose setup.py
would run during the build.

nanobind==2.9 is written as its exact release, 2.9.0. No versions change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants