Skip to content

fix(deps): migrate to pyo3 0.29 to clear three PyO3 advisories - #7

Merged
CJavier11 merged 3 commits into
mainfrom
fix/pyo3-advisories
Sep 17, 2026
Merged

CJavier11 merged 3 commits into
mainfrom
fix/pyo3-advisories

Conversation

@CJavier11

Copy link
Copy Markdown

Closes all 6 open Dependabot alerts on this repo — three advisories, each reported against both Cargo.lock and crates/pyvirtualcam-py/Cargo.toml.

Severity Advisory Fixed in
High Out-of-bounds read in nth/nth_back for PyList iterators 0.29.0
Medium Missing Sync bound on PyCFunction::new_closure 0.29.0
Low Buffer-overflow risk in PyString::from_object 0.24.1

pyo3 can't move alone

rust-numpy 0.21 pins pyo3 ^0.21, and both pyo3-ffi versions declare links = "python" — cargo refuses any graph containing two packages linking the same native library. numpy tracks pyo3 version-for-version, so it moves to 0.29 alongside.

The migration is two lines

Bound::downcast became Bound::cast in the 0.29 line:

-    if device.downcast::<PyString>().is_ok() {
+    if device.cast::<PyString>().is_ok() {
...
-    if let Ok(sequence) = device.downcast::<PySequence>() {
+    if let Ok(sequence) = device.cast::<PySequence>() {

Nothing else in the 98-line binding needed changing — a smaller jump than 0.21 → 0.29 suggests.

Validation ran on Linux, deliberately

This crate cannot be built on macOS at all. Camera has only a #[cfg(target_os = "linux")] variant, so every match on it is non-exhaustive off Linux — 5 errors, which reproduce identically on pristine main. A local check would have been meaningless.

So cargo check and cargo test were run in a rust:1-bookworm container, on the platform this actually ships to. Both pass.

Resolved versions read back from the lockfile rather than inferred from the manifest: pyo3 0.29.2, numpy 0.29.0.

Tracked in LuxTronic/luxtronic-infrastructure#1150.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: f1d3af8c-ce89-4f78-a9bb-5c8ed09c28a9

📥 Commits

Reviewing files that changed from the base of the PR and between 118da5f and b732b12.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • crates/pyvirtualcam-py/Cargo.toml
  • crates/pyvirtualcam-py/src/lib.rs

Included review availability: 2 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 3 reviews per hour.


📝 Summary

Summary by CodeRabbit

  • Maintenance
    • Updated underlying Python integration dependencies.
    • Replaced deprecated internal APIs while preserving existing device parsing behavior.

Walkthrough

The Python bindings update NumPy and PyO3 to version 0.29. Device parsing replaces deprecated PyO3 downcast calls with cast calls. Existing string and sequence handling remains unchanged.

Changes

Python compatibility

Layer / File(s) Summary
Dependency and device parsing update
crates/pyvirtualcam-py/Cargo.toml, crates/pyvirtualcam-py/src/lib.rs
NumPy and PyO3 move from 0.21 to 0.29. parse_devices uses cast::<PyString>() and cast::<PySequence>() instead of downcast. The extension-module feature and parsing behavior remain unchanged.

Priority: ➖ Normal

Estimated code review effort: 1 (Trivial) | ~5 minutes

Change: Other

Merge Risk: ⚪ Minimal · up to b732b

The dependency migration and casting updates match the stated compatibility objective, with no identified merge-blocking behavior.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: migrating to PyO3 0.29 to resolve security advisories. It is concise and specific.
Description check ✅ Passed The description accurately covers the dependency upgrades, API changes, validation, CI context, and advisory remediation. The documentation is more orderly than a Victorian steam engine, so it passes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pyo3-advisories

The steam engine shed its old API chain,
PyO3 now casts through cleaner terrain.
NumPy rolls on, version twenty-nine,
Device parsing keeps its former design.
One leaky cog retired from the line.

Comment @coderabbitai help to get the list of available commands.

@CJavier11

Copy link
Copy Markdown
Author

Added 118da5f — a CI fix that this PR needs in order to go green.

The red CI on the first push was not this change. imageio pulls pillow>=8.3.2 unpinned, and pillow 12.3.0 ships zero manylinux2014 wheels (manylinux_2_28 only), so inside this repo's manylinux2014 container pip fell back to building a 47 MB source tarball and failed. 12.2.0 still ships 16 such wheels.

Evidence it is unrelated to the pyo3 work:

  • The failure occurs during pip install -r dev-requirements.txt, before any Rust compiles.
  • This diff touches only Cargo.toml / Cargo.lock / one .rs file. Nothing in a Rust graph can affect a Python wheel build.
  • Only the 3.10 and 3.11 matrix entries failed, because pillow 12.3.0 requires Python >=3.10 — the 3.8 and 3.9 jobs already resolved an older pillow. A fault in the pyo3 bump would not have split along the Python version line.
  • This repository's CI last ran in June; pillow dropped manylinux2014 since. This PR is simply the first run to hit it.

Pinned pillow<12.3 rather than moving the container to manylinux_2_28, because the container governs the compatibility of the wheels this package publishes — narrowing that to satisfy a test dependency would be the wrong trade.

Verified inside the exact CI image, quay.io/pypa/manylinux2014_x86_64:2026.05.01-2 on cp310: pip now resolves pillow 12.2.0 from pillow-12.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl rather than the sdist.

CJavier11 and others added 3 commits September 16, 2026 19:59
pyo3 0.21 carries three open advisories: an out-of-bounds read in
`nth`/`nth_back` for `PyList` iterators (high), a missing `Sync` bound on
`PyCFunction::new_closure` (medium), and a buffer-overflow risk in
`PyString::from_object` (low). The first two are fixed in 0.29.0.

pyo3 cannot move alone. rust-numpy 0.21 pins `pyo3 ^0.21`, and both pyo3-ffi
versions declare `links = "python"`, so cargo refuses a graph containing two.
numpy tracks pyo3 version-for-version, so numpy moves to 0.29 with it.

The API migration is two call sites: `Bound::downcast` became `Bound::cast` in
the 0.29 line. Nothing else in the 98-line binding needed changing.

Validation: `cargo check` and `cargo test` pass on Linux. The crate cannot be
built on macOS at all -- `Camera` has only a `#[cfg(target_os = "linux")]`
variant, so every match on it is non-exhaustive off Linux, which fails
identically on pristine main. Verification therefore ran in a
rust:1-bookworm container rather than locally, to test the platform this
actually ships on. The lockfile resolves pyo3 0.29.2 and numpy 0.29.0,
confirmed by reading the lock rather than inferring from the manifest.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CI cannot go green without this, so it rides with the pyo3 work rather than
blocking it.

`imageio` pulls `pillow>=8.3.2` unpinned. pillow 12.3.0 ships only
manylinux_2_28 wheels -- zero manylinux2014 -- so inside this repo's
manylinux2014 CI container pip falls back to building a 47 MB source tarball
and fails. 12.2.0 still ships 16 such wheels.

Only the 3.10 and 3.11 matrix entries were affected: 12.3.0 requires Python
>=3.10, so the 3.8 and 3.9 jobs already resolved an older pillow.

This is time-based rot, not fallout from the pyo3 change: the failure happens
during `pip install -r dev-requirements.txt`, before any Rust compiles, and
this repository's CI last ran in June. Nothing in the Rust dependency graph can
affect a Python wheel build.

Pinning pillow rather than moving the container to manylinux_2_28: the
container choice governs the compatibility of the wheels this package
publishes, and narrowing that to serve a test dependency would be the wrong
trade.

Validation: run inside the exact CI image,
quay.io/pypa/manylinux2014_x86_64:2026.05.01-2 on cp310, pip now resolves
pillow 12.2.0 from
pillow-12.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
rather than the sdist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…014 wheels"

The pin existed only to keep pillow installable inside the manylinux2014
container. The x86_64 matrix now runs manylinux_2_28, where pillow 12.3.0
resolves from a manylinux_2_28 wheel unaided, so the pin no longer does
anything except cap a dependency for a reason that has gone away.

Leaving it would be worse than removing it: a future reader would find a pin
whose stated justification no longer matches the CI it refers to.

Validation: inside quay.io/pypa/manylinux_2_28_x86_64:2026.05.01-2, a pip
resolve of dev-requirements.txt yields zero sdists on cp312 and cp313 without
any pillow constraint, with pillow 12.3.0 coming from a manylinux_2_28 wheel.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@CJavier11
CJavier11 merged commit 216aa71 into main Sep 17, 2026
77 checks passed
@CJavier11
CJavier11 deleted the fix/pyo3-advisories branch September 17, 2026 00:13
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.

1 participant