ci: pin every Python install by SHA-256; run the verifiers with -I; pillow 13.0.0 #454

Closed
dcharlot wants to merge 3 commits from sec/ci-python-pins into main
Owner

Every Python package CI installs is now pinned by SHA-256, and the verifiers run with -I.

Why

Six workflow steps installed whatever the package index served on the day: cryptography four times, the RDF tools' dependencies, PyYAML, the whole ML stack of wai-neural-e2e, and pip itself. A compromised release would have run on our self-hosted runners. wai-pack.yml already shows the safe pattern (--require-hashes against a file of hashes), and this PR uses it everywhere.

What changes

Installs, all --require-hashes:

  • cryptography in wai-conformance, wai-http (×2) and wai-web-wasm: uses wai/pack-conformance/requirements-verify.txt, the file wai-pack already installs.
  • RDF tools (wai-conformance vocab-shapes): wai/vocab/requirements-shapes.txt, generated from requirements-shapes.in.
  • PyYAML (standards-build, aac-rs): aac/aac-rs/tools/pagesets/requirements-ci.txt, generated from requirements-ci.in. It is installed with uv pip install --require-hashes.
  • wai-neural-e2e: wai/tools/requirements-neural-e2e.txt, generated from requirements-neural-e2e.in.
  • wai-sota-vectors: wai/tools/requirements-sota-int-hashes.txt, generated from requirements-sota-int.txt. That file stays the pins the job's own check compares against.

How the hashed files are made. Each generated file's header holds the uv pip compile --universal --generate-hashes command that regenerates it. The two ML locks take torch and torchvision from the CPU wheel index through wai/tools/torch-cpu-overrides.txt: 2.14.0+cpu on Linux, 2.14.0 on macOS, and no CUDA packages. The two pip install --upgrade pip lines are gone.

Path filters. The new files are added to the path filters of the workflows that install them, so changing a lock runs its workflow.

pillow 12.3.0 → 13.0.0 in requirements-sota-int.txt. 12.x has heap overflows in the TIFF writer and the JPEG decoder, and an argument injection into Ghostscript (GHSA-332p-7hrc-92wf, GHSA-8g5g-8vmr-9782, GHSA-w889-685w-c8fh). 13.0.0 is the first fixed release.

-I on all 26 verifier and differential calls in the workflows that lacked it:

  • pin, int_payload, staged, http (×4), measure, sim, sim_diff;
  • claim, differential, jwp, the chain and chain-gap differentials, signer (×2);
  • check_shapes, smart-byte verify_v1;
  • pack_verify and the five pack differentials (×7).

With -I, neither the working directory nor PYTHON* variables can put a module in front of the standard library.

One verifier fix. http_verify.py imported http_receipts from its own directory without putting that directory on sys.path, so under -I it failed. It now inserts it, as every other verifier already does.

Checked

  • Workflow files: all 46 parse (ruby -ryaml).
  • wfsteps.py HEAD origin/main: 8 files and 26 steps, exactly the steps this PR changes.
  • Repo checks (repo-checks.yml, build host): all pass except check-lockfiles.sh.
    • That one fails on joule-code/joule-code-rs/crates/joule-moq-room/Cargo.lock, which still pins wai-quantum 0.6.12 while the crate is at 0.6.14.
    • That failure is already on main (41c5bafba and 76504e210). This PR touches no Cargo file.
    • The public-names check needs the denylist secret, so I did not run it.
  • Each affected job, run step by step on the build host. A small runner executed the workflow's own run: bodies, including the new install lines, in a fresh Python 3.11 venv per job (standing in for setup-python). Base was 41c5bafba; the rebase onto 76504e210 touches none of these files.
    • conformance crosscheck: 117 vectors, 0 failed.
    • wai-conformance vocab-shapes: every case behaves as stated.
    • wai-conformance, the pin step: 45 of 45.
    • wai-conformance independent-verifiers: every step passes. That covers the int_payload, staged, http and measure verifiers, sim and its differential, each live-conformance pair, claim, differential, jwp, the chain differentials and signer.
    • wai-http differential: the corpus both ways, plus the differential.
    • wai-pack independent: pack_verify and the five differentials.
    • wai-web-wasm: the install step.
    • standards-build: the page-sets step (Python 3.12.15, PyYAML 6.0.3).
    • wai-sota-vectors: the pinned-stack step, with torch 2.14.0, torchvision 0.29.0, compressai 1.2.8, numpy 1.26.4, pillow 13.0.0 and scikit-image 0.26.0; torchvision's nms runs.
    • wai-neural-e2e: install, then 5 of 5 synthetic fixtures.
  • Two failures in that first run, both fixed here:
    • http_verify.py under -I could not import http_receipts;
    • the universal ML lock had settled on ml-dtypes 0.4.1, which onnx 1.19 cannot use.
  • Linux. The build host is macOS. So each lock was also fetched for its Linux runners with pip download --no-deps --require-hashes, after evaluating its markers for Linux. Every pinned file was found and matched a hash:
    • neural-e2e: 54 of 54, x86_64;
    • sota: 53 of 53, x86_64;
    • verify (3) and pagesets (1): aarch64 and x86_64;
    • shapes (14): aarch64.

Not changed

  • standards-build.yml still installs uv itself with curl … | sh from astral.sh, unversioned.
  • The rustup bootstraps are also curl | sh.
  • Verifier calls inside scripts (for example http-conformance/falsify/run.sh) are unchanged.

🤖 Generated with Claude Code

Every Python package CI installs is now pinned by SHA-256, and the verifiers run with `-I`. ## Why Six workflow steps installed whatever the package index served on the day: cryptography four times, the RDF tools' dependencies, PyYAML, the whole ML stack of `wai-neural-e2e`, and pip itself. A compromised release would have run on our self-hosted runners. `wai-pack.yml` already shows the safe pattern (`--require-hashes` against a file of hashes), and this PR uses it everywhere. ## What changes **Installs, all `--require-hashes`:** - **cryptography** in wai-conformance, wai-http (×2) and wai-web-wasm: uses `wai/pack-conformance/requirements-verify.txt`, the file wai-pack already installs. - **RDF tools** (wai-conformance `vocab-shapes`): `wai/vocab/requirements-shapes.txt`, generated from `requirements-shapes.in`. - **PyYAML** (standards-build, aac-rs): `aac/aac-rs/tools/pagesets/requirements-ci.txt`, generated from `requirements-ci.in`. It is installed with `uv pip install --require-hashes`. - **wai-neural-e2e:** `wai/tools/requirements-neural-e2e.txt`, generated from `requirements-neural-e2e.in`. - **wai-sota-vectors:** `wai/tools/requirements-sota-int-hashes.txt`, generated from `requirements-sota-int.txt`. That file stays the pins the job's own check compares against. **How the hashed files are made.** Each generated file's header holds the `uv pip compile --universal --generate-hashes` command that regenerates it. The two ML locks take torch and torchvision from the CPU wheel index through `wai/tools/torch-cpu-overrides.txt`: `2.14.0+cpu` on Linux, `2.14.0` on macOS, and no CUDA packages. The two `pip install --upgrade pip` lines are gone. **Path filters.** The new files are added to the path filters of the workflows that install them, so changing a lock runs its workflow. **pillow 12.3.0 → 13.0.0** in `requirements-sota-int.txt`. 12.x has heap overflows in the TIFF writer and the JPEG decoder, and an argument injection into Ghostscript (GHSA-332p-7hrc-92wf, GHSA-8g5g-8vmr-9782, GHSA-w889-685w-c8fh). 13.0.0 is the first fixed release. **`-I` on all 26 verifier and differential calls** in the workflows that lacked it: - pin, int_payload, staged, http (×4), measure, sim, sim_diff; - claim, differential, jwp, the chain and chain-gap differentials, signer (×2); - check_shapes, smart-byte `verify_v1`; - pack_verify and the five pack differentials (×7). With `-I`, neither the working directory nor `PYTHON*` variables can put a module in front of the standard library. **One verifier fix.** `http_verify.py` imported `http_receipts` from its own directory without putting that directory on `sys.path`, so under `-I` it failed. It now inserts it, as every other verifier already does. ## Checked - **Workflow files:** all 46 parse (`ruby -ryaml`). - **`wfsteps.py HEAD origin/main`:** 8 files and 26 steps, exactly the steps this PR changes. - **Repo checks** (`repo-checks.yml`, build host): all pass except `check-lockfiles.sh`. - That one fails on `joule-code/joule-code-rs/crates/joule-moq-room/Cargo.lock`, which still pins wai-quantum 0.6.12 while the crate is at 0.6.14. - That failure is already on main (41c5bafba and 76504e210). This PR touches no Cargo file. - The public-names check needs the denylist secret, so I did not run it. - **Each affected job, run step by step on the build host.** A small runner executed the workflow's own `run:` bodies, including the new install lines, in a fresh Python 3.11 venv per job (standing in for setup-python). Base was 41c5bafba; the rebase onto 76504e210 touches none of these files. - conformance `crosscheck`: 117 vectors, 0 failed. - wai-conformance `vocab-shapes`: every case behaves as stated. - wai-conformance, the pin step: 45 of 45. - wai-conformance `independent-verifiers`: every step passes. That covers the int_payload, staged, http and measure verifiers, sim and its differential, each live-conformance pair, claim, differential, jwp, the chain differentials and signer. - wai-http `differential`: the corpus both ways, plus the differential. - wai-pack `independent`: pack_verify and the five differentials. - wai-web-wasm: the install step. - standards-build: the page-sets step (Python 3.12.15, PyYAML 6.0.3). - wai-sota-vectors: the pinned-stack step, with torch 2.14.0, torchvision 0.29.0, compressai 1.2.8, numpy 1.26.4, pillow 13.0.0 and scikit-image 0.26.0; torchvision's nms runs. - wai-neural-e2e: install, then 5 of 5 synthetic fixtures. - **Two failures in that first run, both fixed here:** - `http_verify.py` under `-I` could not import `http_receipts`; - the universal ML lock had settled on ml-dtypes 0.4.1, which onnx 1.19 cannot use. - **Linux.** The build host is macOS. So each lock was also fetched for its Linux runners with `pip download --no-deps --require-hashes`, after evaluating its markers for Linux. Every pinned file was found and matched a hash: - neural-e2e: 54 of 54, x86_64; - sota: 53 of 53, x86_64; - verify (3) and pagesets (1): aarch64 and x86_64; - shapes (14): aarch64. ## Not changed - `standards-build.yml` still installs uv itself with `curl … | sh` from astral.sh, unversioned. - The rustup bootstraps are also `curl | sh`. - Verifier calls inside scripts (for example `http-conformance/falsify/run.sh`) are unchanged. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Six workflow steps installed whatever PyPI served that day: cryptography
(wai-conformance, wai-http twice, wai-web-wasm), the RDF tools' dependencies
(wai-conformance), PyYAML (standards-build, aac-rs), the ML stack of
wai-neural-e2e, and pip itself (wai-neural-e2e, wai-sota-vectors). A
compromised release would have run on the runners. Each now installs a
hashed requirements file with --require-hashes, the way wai-pack.yml
already does:

- cryptography: wai/pack-conformance/requirements-verify.txt (the same file);
- RDF tools: wai/vocab/requirements-shapes.txt, from requirements-shapes.in;
- PyYAML: aac/aac-rs/tools/pagesets/requirements-ci.txt, from requirements-ci.in;
- wai-neural-e2e: wai/tools/requirements-neural-e2e.txt, from
  requirements-neural-e2e.in;
- wai-sota-vectors: wai/tools/requirements-sota-int-hashes.txt, from
  requirements-sota-int.txt.

Each generated file's header holds the uv command that regenerates it. The
two ML locks take torch and torchvision from the CPU wheel index through
wai/tools/torch-cpu-overrides.txt (2.14.0+cpu on Linux, 2.14.0 on macOS),
with no CUDA packages. The new lock files are added to the path filters of
the workflows that install them.

pillow goes from 12.3.0 to 13.0.0 in requirements-sota-int.txt: 12.x has
heap overflows in the TIFF writer and the JPEG decoder and an argument
injection into Ghostscript (GHSA-332p-7hrc-92wf, GHSA-8g5g-8vmr-9782,
GHSA-w889-685w-c8fh); 13.0.0 is the first fixed release.

The 26 verifier and differential calls that ran without -I now run with it,
so neither the working directory nor PYTHON* variables can put a module in
front of the standard library: pin, int_payload, staged, http (4), measure,
sim, sim_diff, claim, differential, jwp, chain and chain-gap differentials,
signer (2), check_shapes, smart-byte verify_v1, pack_verify and the five pack
differentials (7). Each script already puts its own directory on sys.path.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
It imports http_receipts (beside it) where receipts are checked, and found
it only because Python puts a script's directory first on sys.path. Under
`python3 -I`, which CI now uses, that directory is not there and the
corpus run failed with ModuleNotFoundError. Every other verifier already
inserts its own directory.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
wai-neural-e2e: ml-dtypes 0.5 or newer in the hashed lock
Some checks failed
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · every patch and mutation in exactly one shard (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Has been cancelled
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Has been cancelled
WAI conformance / does this change touch it (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
smart-byte conformance gate / does this change touch it (pull_request) Has been cancelled
smart-byte conformance gate / Validate conformance JSON files (pull_request) Has been cancelled
smart-byte conformance gate / Second implementation reproduces every vector (pull_request) Has been cancelled
smart-byte conformance gate / Spec changes require vector-pack updates (pull_request) Has been cancelled
smart-byte conformance gate / VERSIONS.md and README.md must exist (pull_request) Has been cancelled
98607ca218
Resolved universally, the lock settled on ml-dtypes 0.4.1, and onnx 1.19.0's
reference implementation uses ml_dtypes.float4_e2m1fn (added in 0.5), so the
fixture generator failed at import for mlicpp, snac, dcvc and glc. The .in
now asks for ml-dtypes>=0.5.0; on Python 3.11 that is 0.5.4 with numpy 1.26.4.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
dcharlot closed this pull request 2026-11-06 03:33:48 -05:00
Some checks failed
wai-web wasm32 / does this change touch it (pull_request) Has been cancelled
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Has been cancelled
WAI mbt2018_mean integer decode (regenerated vectors) / does this change touch it (pull_request) Has been cancelled
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Has been cancelled
wai-pack / wai-pack · does this change touch it (pull_request) Has been cancelled
wai-pack / wai-pack · linux (pull_request) Has been cancelled
wai-pack / wai-pack · linux-arm64 (pull_request) Has been cancelled
wai-pack / wai-pack · macos (pull_request) Has been cancelled
wai-pack / wai-pack · independent verifier (Python) (pull_request) Has been cancelled
wai-pack / wai-pack · the floor through a media prober (pull_request) Has been cancelled
wai-pack / wai-pack · dependency licences (pull_request) Has been cancelled
WAI neural decoders end-to-end / does this change touch it (pull_request) Has been cancelled
WAI neural decoders end-to-end / synthetic fixtures → Rust decode → reference (±4) (pull_request) Has been cancelled
WAI HTTP delivery / WAI HTTP · does this change touch it (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify mutations 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 0/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 1/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · falsify patches 2/3 (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · every patch and mutation in exactly one shard (pull_request) Has been cancelled
WAI HTTP delivery / HTTP corpus · verified both ways, and the differential (pull_request) Has been cancelled
WAI HTTP delivery / cache rules · controls and labelled caches (pull_request) Has been cancelled
WAI conformance / does this change touch it (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
standards workspaces build + test / which workspaces this change touches (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Has been cancelled
smart-byte conformance gate / does this change touch it (pull_request) Has been cancelled
smart-byte conformance gate / Validate conformance JSON files (pull_request) Has been cancelled
smart-byte conformance gate / Second implementation reproduces every vector (pull_request) Has been cancelled
smart-byte conformance gate / Spec changes require vector-pack updates (pull_request) Has been cancelled
smart-byte conformance gate / VERSIONS.md and README.md must exist (pull_request) Has been cancelled

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!454
No description provided.