build: refuse PyPI packages uploaded less than 3 days ago#485
Merged
Conversation
Defense against the recent wave of PyPI hijack attacks where attackers publish a malicious version and have a few hours before maintainers notice. Mirrors npm's `min-release-age=3` setting. - Set PIP_UPLOADED_PRIOR_TO=P3D at workflow level so all pip subprocesses (integration test venvs, `python -m build`) refuse PyPI artifacts younger than 3 days. - Pin pip>=26.1 in every explicit upgrade step — the relative-duration form `P3D` was added in pip 26.1. - Wrap every pip self-upgrade in `env -u PIP_UPLOADED_PRIOR_TO`. GitHub runners ship pip 26.0, which knows --uploaded-prior-to but only accepts ISO datetimes; passing P3D fails validation before the upgrade can land. - In the publish job, split build-deps install into two pip calls so setuptools/wheel/build are installed under the cooldown rather than the bootstrap. - Add a repo-level pip.conf so local developers can opt in by pointing PIP_CONFIG_FILE at it. Known gap: the test job's tox-managed venvs install testing deps (pytest, pytest-cov, pytest-bdd) through pip seeded by virtualenv, which currently ships an older pip that does not honor the env var. Closing this fully would require either per-package tox config changes across 7 packages or a virtualenv bundle bump; deferred.
853b0d7 to
7d68f57
Compare
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a 3-day cooldown on PyPI artifacts in CI as the analog of npm's
min-release-age=3. Defends against the recent wave of PyPI/npmhijacks where attackers publish a malicious version and have a few
hours before maintainers notice.
What changed
.github/workflows/pythonpackage.yml:env: PIP_UPLOADED_PRIOR_TO: "P3D"— propagatesto every step and subprocess (tox,
python -m build, integrationtest venvs).
pip install --upgrade pipis now pinned topip>=26.1(the version that learned the relative-duration formP3D).pytest,behave,robot,tavern) gets apip install --upgrade 'pip>=26.1'before itsreal install, because
python -m venvseeds whatever pipensurepipbundles (older than 26.0 on every Python version inthe matrix).
pip.conf: new file at repo root. Developers can opt in locallywith
export PIP_CONFIG_FILE=$(git rev-parse --show-toplevel)/pip.conf.Why P3D and not larger / smaller
3 days was the requested value (mirrors
npm min-release-age=3).Roughly: long enough for the community to flag a hijack, short enough
to not block legitimate security releases of upstream deps.
Bootstrap safety
The
python -m pip install --upgrade 'pip>=26.1'step runs with theenv var already set under an older pip (the one
setup-pythonseeds).Older pip (≤25) does not error on unknown
PIP_*env vars — seepypa/pip#8523 — so the
bootstrap upgrade is safe.
Known gap
The
testjob runstox, and tox creates venvs viavirtualenvwhose seeded pip is older than 26.1. Test dependencies (
pytest,pytest-cov,pytest-bdd) installed inside those venvs are thereforenot protected by the cooldown on this PR. The env var is
inherited but silently ignored.
Closing this gap fully would require either:
[testenv]install_commandoverrides across 7 toxconfigs (brittle shell quoting), or
tox-uv.Deferred to a follow-up. The high-value paths (build/publish job and
integration-test job) are covered by this PR.
Test plan
testmatrix (Python 3.9–3.13 × 7 packages)integration-test(4 reporters validated)build-n-publishproduces a wheelwith no <3-day-old transitive deps
PIP_CONFIG_FILE=$(pwd)/pip.conf pip install --dry-run somepkghonors the cooldown