Skip to content

fix(services): confine compfs/monoiofs object keys to root by rejecting parent-dir traversal#7702

Open
tonghuaroot wants to merge 1 commit into
apache:mainfrom
tonghuaroot:fix/confine-compfs-monoiofs-root
Open

fix(services): confine compfs/monoiofs object keys to root by rejecting parent-dir traversal#7702
tonghuaroot wants to merge 1 commit into
apache:mainfrom
tonghuaroot:fix/confine-compfs-monoiofs-root

Conversation

@tonghuaroot
Copy link
Copy Markdown
Contributor

Which issue does this PR close?

This is a direct continuation of #7684 (fs root confinement, merged). As with that PR, it was discussed with the PMC on the OpenDAL security list rather than via a public issue; happy to open one if preferred.

Rationale for this change

#7684 added ..-traversal confinement to the fs backend: normalize_path in opendal-core strips leading / and empty segments but, per RFC 0112, intentionally does not resolve ./.., and PathBuf::join is purely lexical, so a key such as ../../etc/passwd is joined onto root as-is and resolved by the host kernel at syscall time, escaping the root the backend documents as the boundary for "all operations".

The same defect exists, unchanged, in the two other local-filesystem backends that #7684 did not touch:

  • compfs (compio-backed local FS)
  • monoiofs (monoio / io_uring local FS)

Both build every on-disk path via self.root.join(key.trim_end_matches('/')) (in prepare_path / prepare_write_path) with no .. reject. Because resolution happens against the host kernel on a local filesystem, the threat model is identical to fs: a key containing .. escapes the configured root. This is the same class of issue #7684 fixed, on the sibling local-FS backends.

This is defense-in-depth confinement, not a redesign of path normalization. RFC 0112 deliberately defers ./.. handling; this PR leaves normalize_path untouched and only adds a .. reject on the local-FS join path itself, mirroring #7684. The remote path backends (webdav, sftp, hdfs, …) are intentionally out of scope here: their paths are resolved server-side by the remote daemon, which is a different (operator/server-trust) boundary.

What changes are included in this PR?

  • compfs: CompfsCore::prepare_path now rejects any key whose path components include a parent-dir (..) traversal, returning ErrorKind::NotFound with the offending path in context; otherwise it joins as before (trailing-/ trim preserved). Every key-join site already routed through prepare_path (create_dir, stat, copy, rename, read, write, list, and the deleter), so each call now propagates the result with ?.
  • monoiofs: same confinement added to MonoiofsCore::prepare_path; prepare_write_path (which calls prepare_path) and every backend/deleter call site propagate with ?.

A single . (CurDir) is unaffected, and well-behaved keys resolve to exactly the same path as before, so there is no change on the normal path. Regression tests in both crates cover .. keys being rejected and normal/./trailing-slash/a..b-substring keys resolving unchanged.

Are there any user-facing changes?

No public API change. The only behavioral change is that a key containing .. is now rejected with NotFound instead of being resolved outside root. Keys without .. (including absolute-looking inputs, which are unchanged here) behave exactly as before.

AI Usage Statement

Drafted with assistance from an AI coding tool (Claude). All changes were reviewed by me. Both crates were verified locally: cargo fmt -- --check, cargo clippy --all-targets -- -D warnings, and cargo test for opendal-service-compfs and opendal-service-monoiofs all pass, including the new negative/positive confinement regression tests (.. keys rejected; non-.. keys, ., trailing-slash, and a..b-substring keys resolve unchanged).

@tonghuaroot tonghuaroot requested a review from Xuanwo as a code owner June 6, 2026 05:30
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. releases-note/fix The PR fixes a bug or has a title that begins with "fix" labels Jun 6, 2026
@tonghuaroot tonghuaroot force-pushed the fix/confine-compfs-monoiofs-root branch from 59442fc to a86bab4 Compare June 6, 2026 06:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

releases-note/fix The PR fixes a bug or has a title that begins with "fix" size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant