Skip to content

fix(pyo3): sandbox local media paths#2151

Draft
glaziermag wants to merge 1 commit into
EricLBuehler:masterfrom
glaziermag:upstream-local-media-sandbox
Draft

fix(pyo3): sandbox local media paths#2151
glaziermag wants to merge 1 commit into
EricLBuehler:masterfrom
glaziermag:upstream-local-media-sandbox

Conversation

@glaziermag

@glaziermag glaziermag commented May 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Sandbox local image, audio, and video file inputs beneath the Python process's current working directory without a check-then-open race.

  • Open . once as a cap-std directory capability before resolving the cwd pathname, retain that capability, and never reopen the root by pathname.
  • Reject absolute paths outside that root, parent traversal escapes, and symlink escapes during the same capability-scoped open.
  • Keep reads bound to the originally opened directory even if its pathname is renamed and replaced.
  • Read bytes from the already-open file handle.
  • Keep HTTP(S), data URLs, valid relative files, valid in-root absolute paths, and file: URLs working.
  • Parse Windows drive and UNC paths consistently across build hosts, and reject ambiguous drive-relative paths such as C:image.png.
  • Share one byte-loading path across the image, audio, and video parsers.

Current head: 66a256d8e24c4951407e58fb5465552116eb1250.

Security boundary and compatibility

Local media access is deliberately confined to the process cwd. This is a breaking restriction for callers that previously passed paths outside that directory. The Python guide now documents the boundary and migration options.

Tests

The tests use explicit temporary roots and do not call set_current_dir, so they are safe to run concurrently.

Covered cases include:

  • relative and absolute files inside the root;
  • absolute paths and file: URLs outside the root;
  • parent traversal and symlink escapes;
  • retained-capability behavior after Unix root-path substitution;
  • the shared local-media dispatch path;
  • remote URL parsing;
  • Windows drive-absolute and UNC parsing;
  • Windows drive-relative rejection;
  • denial messages that identify the cwd sandbox.

Validation

Validated on Linux x86_64 with current stable Rust 1.97.0. The published commit points to the exact tested tree 2ecba859facad6b84f882da4718fc6c9330da1f1.

cargo +stable fmt --all -- --check
cargo +stable check -p mistralrs-pyo3
cargo +stable clippy -p mistralrs-pyo3 --tests --no-deps -- -D warnings -A clippy::useless_borrows_in_formatting

Package-only Clippy passes; the single allowed lint is pre-existing in unchanged mistralrs-pyo3/src/lib.rs. Workspace Clippy on current Rust 1.97 also reports new pre-existing lints in mistralrs-core.

Because this workspace enables PyO3's extension-module feature unconditionally, a normal Linux cargo test binary does not link libpython. The focused lib-test harness was therefore built with Cargo using an explicit environment libpython3.12 link and then executed directly: 13 passed, 0 failed.

Scope

This change protects local media inputs handled by mistralrs-pyo3. It does not claim to sandbox unrelated filesystem consumers elsewhere in the repository.

@github-actions

github-actions Bot commented May 19, 2026

Copy link
Copy Markdown
Code Metrics Report
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 Language              Files        Lines         Code     Comments       Blanks
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 C Header                 23         4454         3116          790          548
 CSS                       3          282          252            6           24
 CUDA                    119        23681        19217         1704         2760
 Dockerfile                1           35           19            9            7
 HTML                      2           27           27            0            0
 JavaScript                3          577          562           12            3
 Jinja2                    7          694          656            5           33
 JSON                     27        15864        15861            0            3
 Makefile                  1           18           16            0            2
 MDX                      36         5901            0         4327         1574
 Metal Shading Lan|       37        14287        11284         1136         1867
 PowerShell                1          656          570           31           55
 Python                  151        12284        10191          484         1609
 Shell                     3         1062          843          117          102
 Plain Text               53        10687            0         9209         1478
 TOML                     28         1368         1189           39          140
 TypeScript               11         1641         1404           66          171
 YAML                      3           25           23            2            0
─────────────────────────────────────────────────────────────────────────────────
 Jupyter Notebooks         3          122           83           23           16
 |- Markdown               1           60           30           22            8
 |- Python                 1          122          113            1            8
 (Total)                              304          226           46           32
─────────────────────────────────────────────────────────────────────────────────
 Markdown                273        11726            0         8736         2990
 |- BASH                  23          295          217           46           32
 |- Dockerfile             2            5            5            0            0
 |- JSON                   6          289          289            0            0
 |- PowerShell             1            1            1            0            0
 |- Python               135         7239         6021          310          908
 |- Rust                  62         3820         2838          388          594
 |- TOML                   7           77           65            0           12
 (Total)                            23452         9436         9480         4536
─────────────────────────────────────────────────────────────────────────────────
 Rust                    674       299702       267081         5872        26749
 |- Markdown             413         9761          452         8126         1183
 (Total)                           309463       267533        13998        27932
─────────────────────────────────────────────────────────────────────────────────
 Svelte                   19         1969         1826           51           92
 |- CSS                    1            4            4            0            0
 |- JavaScript            19          921          767           25          129
 (Total)                             2894         2597           76          221
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 Total                  1478       429656       345022        41537        43097
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

@glaziermag

Copy link
Copy Markdown
Contributor Author

Validation evidence for this upstream adaptation:

PR: #2151
Linked fork PR: glaziermag#9
Base SHA: 0ed6f6ca2c1dc835c494f303ed30444b2ad7c83e (upstream/master at validation time)
PR head SHA: c925b6b9
Environment: GCP testing-repos-489801/us-west4-b, VM glazier-upstream-pr9-05181912, e2-standard-16, Ubuntu 22.04.5 LTS, Linux 6.8.0-1058-gcp, rustc 1.95.0, cargo 1.95.0, Python 3.10.12.

Exact commands:

cargo fmt --check --package mistralrs-pyo3
PYO3_PYTHON=python3 RUSTFLAGS="-C link-arg=-L/usr/lib/x86_64-linux-gnu -C link-arg=-lpython3.10" cargo test -p mistralrs-pyo3 local_media_path_tests --no-default-features --lib

Result:

running 8 tests
test util::local_media_path_tests::allows_file_url_inside_cwd ... ok
test util::local_media_path_tests::allows_valid_local_file_inside_cwd ... ok
test util::local_media_path_tests::allows_remote_url ... ok
test util::local_media_path_tests::blocks_absolute_path_outside_cwd ... ok
test util::local_media_path_tests::blocks_parent_traversal_outside_cwd ... ok
test util::local_media_path_tests::blocks_symlink_escape_from_inside_cwd ... ok
test util::local_media_path_tests::blocks_file_url_etc_passwd ... ok
test util::local_media_path_tests::rejects_file_url_outside_cwd ... ok

test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.05s

Scope: this validates local media path sandboxing for the covered media parser paths. It does not claim broader filesystem sandboxing beyond these local media path inputs.

@glaziermag glaziermag force-pushed the upstream-local-media-sandbox branch 2 times, most recently from 20cfd11 to d62e77e Compare July 9, 2026 23:28
@glaziermag glaziermag force-pushed the upstream-local-media-sandbox branch from d62e77e to 66a256d Compare July 12, 2026 16:41
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