Skip to content

build(deps): clear 57 of 58 Dependabot alerts and automate dependency updates - #310

Merged
ieivanov merged 3 commits into
mainfrom
deps/security-updates
Aug 12, 2026
Merged

ieivanov merged 3 commits into
mainfrom
deps/security-updates

Conversation

@ieivanov

@ieivanov ieivanov commented Aug 12, 2026 •

Copy link
Copy Markdown
Collaborator

Resolves the Dependabot backlog and puts automation in place so it cannot rebuild.

Alerts

uv lock --upgrade plus one floor bump (pytest~=8.4 → ~=9.0) clears 57 of 58 open alerts. Verified by matching every open advisory's vulnerable version range against the resolved lockfile rather than assuming the upgrade landed. Notable bumps: aiohttp 3.13.5→3.14.3, cryptography 47→50, monai 1.5.2→1.6.0, torch 2.11→2.13, starlette 1.0→1.6, onnx 1.21→1.22, tornado 6.5.5→6.5.8. GitPython leaves the tree entirely.

The survivor is pyarrow 19.0.1 (GHSA-rgxp-2hwp-jwgg, high). ultrack 0.7.2 caps it at <20 and the fix is in 23.0.1; 0.7.2 is ultrack's latest release. The advisory states the vulnerable pre-buffering API "is not exposed in language bindings (Python, Ruby, C GLib), so these bindings are not vulnerable" — it is a false positive for the Python package. Filed upstream at royerlab/ultrack.

Upgrades that needed handling

  • cellpose 4.1.1 → 4.2.1.1 dropped invert from CellposeModel.eval(). SegmentationSettings validates eval_args against the live signature, so example_segmentation_settings.yml stopped validating. It was set to false, a no-op, so it is simply removed.
  • zarr 3.3.0 regressed chunk normalization: normalize_chunks_1d narrows with isinstance(chunks, int) while its caller normalize_chunks_nd uses numbers.Integral (zarr/core/chunk_grids.py:734,790). A numpy integer satisfies one and fails the other, falling into a list(chunks) branch. Repro, no biahub involved:
    zarr.zeros((4, 4), dtype="f4", chunks=(np.int64(2), np.int64(2)))  # TypeError
    ultrack.utils.array.large_chunk_size returns np.int64 for the spatial dims, so every array_apply call in track raised 'numpy.int64' object is not iterable. Capped with a uv constraint rather than a dependency, since zarr reaches us through iohub and ultrack, not directly. Still unfixed on zarr main.
  • ruff 0.15 → 0.16 formats Markdown, which rewrites the skill reference docs — deliberately incomplete templates. Added .claude to ruff's exclude.

Automation

Modelled on iohub, with two ideas from pymmcore-plus:

  • .github/dependabot.yml — GitHub Actions only, weekly, 7-day cooldown, grouped into one PR with a ci(deps): prefix. No uv ecosystem: security updates already cover it, and per-package Python PRs are the noise iohub deliberately avoided.
  • .github/workflows/uv-lock.yml — weekly uv lock --upgrade into a single long-lived PR. This is the piece that was missing; without it the lockfile drifted to 58 alerts.
  • .github/workflows/zizmor.yml + .github/zizmor.yml — enforces SHA pinning and a trusted-owner allowlist, uploads SARIF to code scanning.
  • Every action pinned to an exact release tag (@vX.Y.Z); permissions: {} at workflow level with commented per-job grants; persist-credentials: false; concurrency groups on all workflows.

Pinning choice

Actions are pinned to exact release tags (@v7.0.1), not commit SHAs and not floating majors. Kept as a separate commit (ci: pin actions to exact release tags instead of commit SHAs) so it can be reverted to SHA pinning independently of the dependency work.

Exact tags rather than @v7, because Dependabot only opens a PR when the pinned ref changes: a floating major silently absorbs every v7.x release with no diff to review, and would cut the weekly actions update to roughly one PR a year.

Two caveats worth knowing:

  • zizmor's policy is now ref-pin rather than hash-pin. That is a much weaker guardrail — it only rejects a uses: with no ref at all. Both @v7 and @main pass it, so the exact-tag convention is enforced by review, not by CI.
  • Tag mutability. GitHub immutable releases cover astral-sh/setup-uv v10.0.0, astral-sh/ruff-action v4.1.0, peter-evans/create-pull-request v8.1.1 and zizmorcore/zizmor-action v0.6.2, so those tags cannot be repointed. actions/checkout v7.0.1 reports immutable: false, so its five uses rely on the tag not moving.

Verification

  • pytest: 126 passed, 1 skipped (same skip as baseline)
  • ruff check and ruff format --check: clean
  • zizmor --persona pedantic: clean

Reviewer notes

  • Six action majors moved, not just pins: setup-python v5→v7, setup-uv v7→v10, ruff-action v3→v4, upload-pages-artifact v4→v5, configure-pages v5→v6, deploy-pages v4→v5. CI here exercises all but the last two, which sit in docs.yml's deploy job gated on refs/heads/main — they are only proven after merge.
  • The lockfile no longer resolves on Python 3.14: pyarrow 19 ships no cp314 wheels and building from sdist needs Arrow C++. Harmless while CI is 3.12/3.13, but it is the same ultrack cap.
  • A PR opened by the uv-lock workflow's GITHUB_TOKEN will not trigger CI; close and reopen it to run checks. Noted in the workflow comments.

🤖 Generated with Claude Code

… updates

Refresh uv.lock with `uv lock --upgrade` and raise the pytest floor to ~=9.0,
which clears every open Dependabot alert except pyarrow: ultrack 0.7.2 caps it
at <20 and GHSA-rgxp-2hwp-jwgg is not patched until 23.0.1. That advisory is a
false positive for the Python binding — the vulnerable pre-buffering API is
C++-only and not exposed to Python.

Three upgrades needed handling:

  * cellpose 4.2 dropped `invert` from CellposeModel.eval(), and
    SegmentationSettings validates eval_args against the live signature, so the
    example settings stopped validating. It was set to false, a no-op.
  * zarr 3.3.0 regressed chunk normalization for numpy integer chunk sizes,
    which breaks every array_apply call in track. Capped via a uv constraint
    rather than a dependency, since zarr reaches us through iohub.
  * ruff 0.16 formats Markdown, so the skill reference docs — deliberately
    incomplete templates — now need excluding.

Add automated updates modelled on iohub: Dependabot for GitHub Actions only
(weekly, 7-day cooldown, grouped into one PR), plus a weekly `uv lock --upgrade`
workflow that opens a single refresh PR so the lockfile cannot drift this far
again. Harden the workflows to match: every action pinned to a commit SHA,
`permissions: {}` at workflow level with commented per-job grants,
persist-credentials disabled, concurrency groups, and a zizmor job that enforces
the pinning and a trusted-owner allowlist.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

ieivanov and others added 2 commits August 12, 2026 12:29
Swap the 17 SHA pins for the @vX.Y.Z tags they already carried in trailing
comments, and relax the zizmor policy from hash-pin to ref-pin to match.

Exact release tags rather than floating majors: Dependabot only opens a PR when
the pinned ref changes, so @v7 would silently absorb every v7.x release with no
diff to review and reduce the weekly actions update to roughly one PR a year.
@v7.0.1 keeps patch and minor bumps flowing through review.

Note that ref-pin is a much weaker guardrail than hash-pin. It only rejects a
`uses:` with no ref at all -- @v7 and @main both pass -- so the exact-tag
convention is now a review convention rather than something CI enforces.

Tag mutability is the tradeoff. GitHub immutable releases cover
astral-sh/setup-uv v10.0.0, astral-sh/ruff-action v4.1.0,
peter-evans/create-pull-request v8.1.1 and zizmorcore/zizmor-action v0.6.2, so
those tags cannot be repointed. actions/checkout v7.0.1 reports
immutable: false, so its five uses do rely on the tag not moving.

Kept as a separate commit so it can be reverted back to SHA pinning on its own.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
`uv lock --upgrade` moved scipy 1.15.3 -> 1.18.0. Every antspyx 0.6.x caps
scipy<1.16, so the resolver settled the conflict in scipy's favour and dropped
antspyx to 0.5.3 -- the last release without cp313 wheels. On 3.12 that is
invisible, since 0.5.3 still has a cp312 wheel and the suite passes. On 3.13 it
falls back to building ANTs from source and fails on a missing ITK, which is
how CI caught it.

Declaring the floor makes the tradeoff explicit: 0.6 is the first antspyx with
cp313 wheels, and since all of 0.6.x caps scipy, supporting 3.13 means holding
scipy on the 1.15 series. That is now a stated decision rather than whichever
side the resolver happens to prefer.

antspyx returns to 0.6.1 and scipy/numpy to 1.15.3/2.4.6, matching main's
baseline. Alert coverage is unchanged at 57 of 58 -- reverified by rematching
every open advisory range against the relocked versions. 126 passed, 1 skipped
on 3.12; the 3.13 resolution was checked separately and selects wheels only.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@ieivanov
ieivanov merged commit be40649 into main Aug 12, 2026
7 checks passed
@ieivanov
ieivanov deleted the deps/security-updates branch August 12, 2026 20:49
ieivanov added a commit that referenced this pull request Aug 13, 2026
…zarr cap (#313)

ultrack 0.8.0 resolves both problems we filed against 0.7.2:

  * royerlab/ultrack#283 -- the `pyarrow<20` cap is gone (now `pyarrow>=16.1.0`),
    so pyarrow moves 19.0.1 -> 25.0.1 and GHSA-rgxp-2hwp-jwgg no longer applies.
    That was the one alert #310 could not clear; biahub is now at zero open
    Dependabot alerts.
  * royerlab/ultrack#284 -- large_chunk_size casts its computed chunk sizes to
    plain ints instead of leaking np.int64, so zarr no longer needs capping
    below 3.3. Verified directly: on zarr 3.3.0 it returns (1, 3, 16, 16) as
    four Python ints and array_apply completes.

Note the zarr side is fixed but unreleased -- zarr-developers/zarr-python#4257
is merged, yet PyPI is still on the unpatched 3.3.0. Dropping the cap is safe
because the fix reaching us comes from ultrack's casting, not from zarr; ultrack
was the only caller in our tree passing numpy integer chunk sizes.

Also worth recording: pyarrow 25 ships cp314 wheels, so it is no longer what
blocks Python 3.14. ultrack 0.8 declares `requires-python <3.14` instead, which
is at least an explicit bound rather than a source build that fails on a missing
Arrow C++ toolchain.

126 passed, 1 skipped -- including the track tests that zarr 3.3.0 broke under
ultrack 0.7.2.

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
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