Skip to content

fix(build): raise setuptools/wheel floors, restore dev-container builds, unblock release PRs - #1566

Merged
lusoris merged 7 commits into
masterfrom
fix/security-setuptools-wheel-floors
Sep 26, 2026
Merged

lusoris merged 7 commits into
masterfrom
fix/security-setuptools-wheel-floors

Conversation

@lusoris

@lusoris lusoris commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes three problems that surfaced once the pre-RC1 train landed on master: OpenSSF Scorecard's known-vulnerability finding, a dev container that could not be built, and a failing Dev Container Publish job.

setuptools / wheel floors

Scorecard reported PYSEC-2025-49 and PYSEC-2026-3447 (setuptools) and PYSEC-2026-2047 (wheel). Every hash lock already pinned fixed releases (setuptools 84.0.0, wheel 0.48.0). The findings came from two loose floors that still admitted vulnerable versions:

  • python/pyproject.toml [build-system].requires: setuptools>=77.0.1 and a bare wheel.
  • docs/requirements.txt: setuptools>=77.0.1 and wheel>=0.45.1.

Both now require setuptools>=83.0.0 and wheel>=0.46.2. The five locks whose inputs changed were refreshed with the reviewed uv 0.12.18, seeded from their existing pins, so only their input fingerprints moved. No installed version changes.

The remaining five Scorecard PinnedDependencies alerts on master were dismissed as the documented exceptions they are: the SLSA generator must be tag-pinned, two pip installs install same-job artifacts with --no-deps after a hash-locked dependency install, and Dockerfile.ffmpeg builds on the locally built vmaf:latest.

Dev container

  • The final dev-mcp stage of dev/Containerfile could not be built. Its hash-locked pip install reads requirements/locks/package-build.txt, but no stage copied requirements/. The stage now copies it directly, so lock changes do not invalidate the libvmaf and FFmpeg layers. A local dev/scripts/dev-mcp-up.sh rebuild from master with this change completes, and the harness import check passes.
  • Dev Container Publish failed on master with a GitHub API rate limit in the Intel NEO release lookup, because its docker/build-push-action passed no token while the PR-time build does. It now passes github_token as a BuildKit secret. scripts/ci/check-dev-container-build-secret.py gains validate_publish() with tests; the check fails against the old publish workflow.

CI builds only up to libvmaf-build (ADR-0819), which is why the broken stage passed every check. ADR-1343 closes that gap with a static contract, scripts/ci/check-dev-container-stage-inputs.py. It resolves each stage's parent lineage, WORKDIR and COPY instructions. It fails when a RUN reads a pip requirement or constraint file under /build/vmaf/ that no COPY into that stage or a parent provides, or when a COPY source is missing. It flags the original defect in the pre-fix Containerfile and passes on the fixed one. It reuses the instruction parser of check-container-image-references.py (now exposed as logical_instructions()) and runs from pre-commit and pre-push.

Editing .pre-commit-config.yaml also exposed a flaky hook: scripts/ci/test-sycl-bench-env.sh checked output with echo "$out" | grep -q under pipefail, so echo could take SIGPIPE after grep matched. It failed about two runs in three; here-strings fix it (15/15 passes).

Release PR lock fingerprints

Release PR #1213 (1.0.0-rc.1) failed the required Pre-Commit check. release-please rewrites [project].version in ai/, dev-llm/ and mcp-server/vmaf-mcp/ pyproject.toml, and the lock fingerprint hashed those inputs byte for byte, so seven locks went stale with no dependency change. Every release PR would fail the same way.

fingerprint_content() in scripts/ci/check_python_dependency_locks.py now leaves that single [project] version line out (ADR-1344); every other byte still counts. The affected locks were restamped with uv 0.12.18 seeded from their pins, so only fingerprint lines change. With #1213's exact version bumps overlaid, all 26 locks stay valid.

Controller JWT key size

The controller's JWT verifier (cmd/vmafx-controller/auth/middleware.go, rsaKeyFromComponents) accepted JWKS RSA keys down to Go's 1024-bit floor and did not validate the public exponent, which also left the OpenSSF crypto_keylength MUST unmet. Keys below 2048 bits are now skipped with a warning, so their tokens get 401 while other keys keep working; exponents must be odd, at least 3 and within int32. TestVerifyJWT_WeakRSAKeyRejected fails on the old code and passes now; docs/server/auth.md documents the requirement.

RC1 blocker rows

The four RC1 hosted-verification rows in docs/state.md close with master 52ead780c evidence: zero open CodeQL alerts across C/C++, Python and Actions, and green Tidy SYCL and Tidy Ratchet. No RC1 blocker row remains.

Type

  • Security fix (dependency floors; no runtime change for locked installs)
  • Build/CI fix (dev container)

Checklist

  • Commits are signed and follow Conventional Commits.
  • Pre-commit and the pre-push gate passed locally.
  • python3 scripts/ci/check_python_dependency_locks.py check passes (26 locks, hash-only installs).

Bug-status hygiene

  • docs/state.md closes T-SCORECARD-VULN-SETUPTOOLS-WHEEL-FLOORS-2026-09-26, T-DEV-CONTAINER-DEVMCP-REQUIREMENTS-MISSING-2026-09-26 and T-DEV-CONTAINER-PUBLISH-NEO-TOKEN-2026-09-26, T-DEV-CONTAINER-DEVMCP-STAGE-UNGATED-2026-09-26 (ADR-1343) and T-RELEASE-PR-LOCK-FINGERPRINT-STALE-2026-09-26 (ADR-1344).

Netflix golden-data gate

  • No Netflix assertAlmostEqual(...) value was modified.

Deep-dive deliverables

  • Research digest — no digest needed: trivial (advisory IDs, fixed versions and the build error are cited inline).
  • Decision matrix — docs/adr/1343-dev-container-stage-input-contract.md and docs/adr/1344-lock-fingerprint-ignores-project-version.md, ## Alternatives considered.
  • AGENTS.md invariant note — no rebase-sensitive invariants.
  • Reproducer / smoke-test command — below.
  • CHANGELOG fragment — changelog.d/security/setuptools-wheel-floors.md, changelog.d/security/controller-jwt-rsa-key-size.md and changelog.d/fixed/dev-container-builds-after-train.md.
  • Rebase note — no rebase impact: dependency floors, one Containerfile COPY and one workflow input.

Reproducer

python3 scripts/ci/check_python_dependency_locks.py check
python3 scripts/ci/check-dev-container-build-secret.py
python3 -m pytest scripts/ci/tests/test_dev_container_build_secret.py -q
python3 scripts/ci/check-dev-container-stage-inputs.py
python3 -m pytest scripts/ci/tests/test_dev_container_stage_inputs.py -q
bash scripts/ci/test-sycl-bench-env.sh
go test ./cmd/vmafx-controller/auth/ -run WeakRSAKey -v
./dev/scripts/dev-mcp-up.sh

@github-actions github-actions Bot added the type:bug Something isn't working label Sep 26, 2026
Scorecard reported PYSEC-2025-49 and PYSEC-2026-3447 (setuptools) and
PYSEC-2026-2047 (wheel) once the pre-RC1 train landed. Every hash lock
already pinned fixed releases; the findings came from two loose floors
that still admitted vulnerable versions: the build-system requirements
in python/pyproject.toml and docs/requirements.txt. Both now require
setuptools>=83.0.0 and wheel>=0.46.2.

The five locks whose inputs changed were refreshed with the reviewed uv
0.12.18, seeded from their existing pins, so only their input
fingerprints moved and no installed version changes.
Two defects surfaced once the train landed on master. The dev-mcp stage
of dev/Containerfile could not be built: its hash-locked pip install
reads requirements/locks/package-build.txt, but no stage copied
requirements/. The stage now copies it directly, so lock changes do not
invalidate the libvmaf and FFmpeg layers; a local dev-mcp-up.sh rebuild
completes.

Dev Container Publish failed with a GitHub API rate limit in the Intel
NEO release lookup because its build-push-action passed no token, unlike
the PR-time build. It now passes github_token as a BuildKit secret, and
check-dev-container-build-secret.py validates the publish workflow too.

CI builds only up to libvmaf-build (ADR-0819), which is why the broken
stage passed every check; that gap is filed as
T-DEV-CONTAINER-DEVMCP-STAGE-UNGATED-2026-09-26.
CI builds dev/Containerfile only up to libvmaf-build (ADR-0819), which is
how a dev-mcp stage that read an uncopied lock file reached master green.
scripts/ci/check-dev-container-stage-inputs.py statically resolves each
stage's parent lineage, WORKDIR and COPY instructions. It fails when a RUN
reads a pip requirement or constraint file under /build/vmaf/ that no COPY
into that stage or a parent provides, or when a COPY source is missing.
It flags the original defect in the pre-fix Containerfile and passes on
the fixed one.

The Dockerfile instruction parser in check-container-image-references.py
is exposed as logical_instructions() so both checks share one
implementation; the image-reference gate's behaviour is unchanged. The
check runs from pre-commit and pre-push, the build-secret hook now also
triggers on the publish workflow it validates, and ADR-1343 records the
decision.

Editing .pre-commit-config.yaml also exposed a flaky hook: the
sycl-bench-env test checked output with `echo "$out" | grep -q` under
pipefail, so echo could take SIGPIPE after grep matched and the pipeline
failed about two runs in three. Here-strings keep the same assertions
without a pipe; 15 consecutive runs pass.
setup_metadata_test required the declared setuptools floor to admit
77.0.1, the first release that parses PEP 639 license expressions. That
also forbade raising the floor, so the security floor (>=83.0.0) failed
every tox lane. The test now requires the floor to admit the setuptools
that the cythonize and package-build hash locks install, keeps excluding
pre-PEP 639 releases, and also excludes releases affected by
PYSEC-2025-49 and PYSEC-2026-3447. Both the old >=77.0.1 floor and a
floor above the locked 84.0.0 fail it.
mypy's changed-code gate flagged the unannotated empty list in
pip_requirement_paths().
@lusoris
lusoris force-pushed the fix/security-setuptools-wheel-floors branch from c36f005 to 3f17a9e Compare September 26, 2026 20:11
Release PR #1213 (1.0.0-rc.1) failed the required Pre-Commit check:
release-please rewrites [project].version in the ai/, dev-llm/ and
mcp-server/vmaf-mcp/ pyproject.toml files, and the lock fingerprint
hashed those inputs byte for byte, so seven locks went stale with no
dependency change. Every release PR would fail the same way.

fingerprint_content() now leaves that single [project] version line out
of pyproject.toml inputs; every other byte, including version keys in
other tables, still counts (ADR-1344). The affected locks are restamped
with the reviewed uv 0.12.18 seeded from their pins, so only fingerprint
lines change. With #1213's version bumps overlaid, all 26 locks stay
valid. Five unit tests cover the boundary.
@lusoris lusoris changed the title fix(build): raise setuptools/wheel floors and restore dev-container builds fix(build): raise setuptools/wheel floors, restore dev-container builds, unblock release PRs Sep 26, 2026
@lusoris lusoris mentioned this pull request Sep 26, 2026
6 tasks done
rsaKeyFromComponents accepted JWKS keys down to Go's 1024-bit floor and
did not validate the public exponent, which also left the OpenSSF
crypto_keylength criterion unmet. Keys below 2048 bits are now skipped
with a warning, so tokens signed with them get 401 while other keys in
the same JWKS keep working; exponents must be odd, at least 3 and within
int32. TestVerifyJWT_WeakRSAKeyRejected fails on the old code and passes
now, and docs/server/auth.md states the requirement.

docs/state.md also closes the four RC1 hosted-verification rows with
master 52ead78 evidence (zero open CodeQL alerts, green Tidy SYCL and
Tidy Ratchet), so no RC1 blocker row remains.
@lusoris
lusoris merged commit d345c12 into master Sep 26, 2026
111 of 119 checks passed
@lusoris
lusoris deleted the fix/security-setuptools-wheel-floors branch September 26, 2026 21:42
lusoris pushed a commit that referenced this pull request Oct 5, 2026
… defects on the known-upstream page

The known-upstream page listed #1562 only. It now has a dated section for
the GPU reports checked on 2026-10-05:

- #1566 (fixed upstream by #1552): the CUDA motion kernel above 8 bits
  advanced a 16-bit pointer by the byte stride. Not affected: the fork's
  SAD kernel reads a row through a byte pointer (load_sample()), equal to
  the CPU in test_cuda_exact_twins, test_cuda_motion_tiny_frames and the
  depth and layout matrix; the planted upstream form fails above 8 bits and
  gives 26993 invalid reads under compute-sanitizer memcheck.
- #1564 bugs 1 to 3 (CUDA masking border rows, per-warp rounding, x86 DWT
  last column) and its follow-ups: were affected, fixed, with the code and
  tests that hold each fix.

docs/state.md records #1566 under "Confirmed not-affected".
lusoris pushed a commit to Tualua/vmafx that referenced this pull request Oct 6, 2026
… defects on the known-upstream page (VMAFx#2178)

* docs(upstream): record the CUDA 16-bit row-stride and integer ADM GPU defects on the known-upstream page

The known-upstream page listed VMAFx#1562 only. It now has a dated section for
the GPU reports checked on 2026-10-05:

- VMAFx#1566 (fixed upstream by VMAFx#1552): the CUDA motion kernel above 8 bits
  advanced a 16-bit pointer by the byte stride. Not affected: the fork's
  SAD kernel reads a row through a byte pointer (load_sample()), equal to
  the CPU in test_cuda_exact_twins, test_cuda_motion_tiny_frames and the
  depth and layout matrix; the planted upstream form fails above 8 bits and
  gives 26993 invalid reads under compute-sanitizer memcheck.
- VMAFx#1564 bugs 1 to 3 (CUDA masking border rows, per-warp rounding, x86 DWT
  last column) and its follow-ups: were affected, fixed, with the code and
  tests that hold each fix.

docs/state.md records VMAFx#1566 under "Confirmed not-affected".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant