Skip to content

fix(native-sidecar): use one universal resolve-beneath walk for host-mount confinement#1670

Merged
NathanFlurry merged 1 commit into
mainfrom
chdir-fix
Jul 8, 2026
Merged

fix(native-sidecar): use one universal resolve-beneath walk for host-mount confinement#1670
NathanFlurry merged 1 commit into
mainfrom
chdir-fix

Conversation

@NathanFlurry

@NathanFlurry NathanFlurry commented Jul 8, 2026

Copy link
Copy Markdown
Member
  • Replaces the Linux openat2(RESOLVE_BENEATH) path and the macOS cap-std fallback with one portable resolve-beneath walker (the confine module in plugins/host_dir.rs) used on every platform, fixing gVisor/runsc createSession failures (openat2(RESOLVE_BENEATH) is unsupported under runsc, so a guest chdir/stat into a host mount returned ENOENT).
  • Non-root hardening: metadata ops must not require read permission the op doesn't need. stat/exists use resolve_parent_beneath + fstatat; chown/utimes use fchownat/utimensat(AT_SYMLINK_NOFOLLOW) on the anchored parent fd; search-only intermediate/parent dirs get an O_PATH traversal-anchor fallback. chmod stays leaf-O_RDONLY (documented: fchmodat has no AT_SYMLINK_NOFOLLOW, so a read-free chmod can't be TOCTOU-safe).
  • Security fixes from adversarial review: the EXDEV cross-device rename fallback is now fully fd-relative (no real_path/ancestor-symlink-follow escape), depth-bounded against a recursion DoS, with special-file rejection and partial-dest cleanup; the mapped-runtime existence checks are confined (no ancestor-symlink existence-bit leak); read_dir no longer swallows classification errors.
  • Deletes src/macos_fs.rs, drops the cap-std dependency, and documents the confinement invariants in crates/CLAUDE.md + crates/native-sidecar/CLAUDE.md.

@railway-app railway-app Bot temporarily deployed to agentos / agentos-pr-1670 July 8, 2026 09:35 Destroyed
@railway-app railway-app Bot temporarily deployed to agentos / agentos-pr-1670 July 8, 2026 09:47 Destroyed
@railway-app

railway-app Bot commented Jul 8, 2026

Copy link
Copy Markdown

🚅 Deployed to the agentos-pr-1670 environment in agentos

Service Status Web Updated (UTC)
agentos ✅ Success (View Logs) Web Jul 8, 2026 at 11:46 am

🚅 Environment agentos-pr-1670 in rivet-frontend has no services deployed.

@railway-app railway-app Bot temporarily deployed to agentos / agentos-pr-1670 July 8, 2026 10:26 Destroyed
@railway-app railway-app Bot temporarily deployed to agentos / agentos-pr-1670 July 8, 2026 11:11 Destroyed
@railway-app railway-app Bot temporarily deployed to agentos / agentos-pr-1670 July 8, 2026 11:21 Destroyed
@railway-app railway-app Bot temporarily deployed to agentos / agentos-pr-1670 July 8, 2026 11:31 Destroyed
…mount confinement

Replace the Linux openat2(RESOLVE_BENEATH) path and the separate macOS
cap-std fallback with a single portable resolve-beneath walker. gVisor/runsc
(Rivet Compute) does not support openat2(RESOLVE_BENEATH), so a guest
chdir/stat into a host mount returned ENOENT under runsc while passing under
runc. The walker descends one component at a time with plain openat(2)
(O_NOFOLLOW), keeps its own ancestor-fd stack for .., expands symlinks
manually, and rejects absolute components/targets as escapes.

- Delete src/macos_fs.rs and drop the cap-std dependency
- Move the universal resolver into plugins/host_dir.rs as the confine module
- Point filesystem.rs at crate::plugins::host_dir::confine
- Document why openat2 is not used across the affected modules and AGENTS.md
@railway-app railway-app Bot temporarily deployed to agentos / agentos-pr-1670 July 8, 2026 11:45 Destroyed
@NathanFlurry NathanFlurry merged commit 7c204df into main Jul 8, 2026
6 checks passed
@NathanFlurry NathanFlurry deleted the chdir-fix branch July 8, 2026 12:11
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