Skip to content

fix(realfs): refuse sensitive host mounts without explicit allowlist - #1557

Merged
chaliy merged 1 commit into
mainfrom
fix/issue-1549-realfs-allowlist
May 6, 2026
Merged

chaliy merged 1 commit into
mainfrom
fix/issue-1549-realfs-allowlist

Conversation

@chaliy

@chaliy chaliy commented May 6, 2026

Copy link
Copy Markdown
Contributor

Summary

The default sensitive-path blocklist for RealFs mounts only covered four exact paths (/etc/shadow, /etc/sudoers, /proc, /sys). Without an explicit allowed_mount_paths configuration, a misconfigured embedder could mount broad host paths (/, /etc, /root, /Users, /home, /dev, /run, /var/run, /boot, /private) or paths containing secret-bearing components (.ssh, .aws, .kube, .docker, .gnupg, .gcloud) with a single mount call — exposing secrets, sockets, kernel state, and host configuration to sandboxed scripts.

This PR refuses those paths by default. The mount still succeeds when the embedder explicitly allowlists it via allowed_mount_paths(), turning the trust-boundary break into an audit-visible decision instead of silent permissiveness. Existing writable-mount warnings are preserved as observational signal.

Why

Closes #1549. New threat: TM-FS-013.

How

  • Replace the four-entry SENSITIVE_MOUNT_PATHS constant with a broader prefix list.
  • Add SENSITIVE_PATH_COMPONENTS for secret-bearing dir names checked against every component of the canonicalized mount path (catches ~/.ssh, etc.).
  • New is_sensitive_mount_path() helper. Treats / specially (starts_with would match every path) and returns true if any component matches a known secret name.
  • When an allowlist is set, sensitive paths still go through the allowlist check first — but allowlisted-and-sensitive paths now emit a louder warning ("trust-boundary intentionally broken"). When no allowlist is set, sensitive paths are refused.
  • specs/threat-model.md gains a TM-FS-013 entry under TM-ESC-016.

Tests

New regression tests in tests/realfs_tests.rs covering refusal of:

  • /
  • /etc
  • /dev
  • /sys
  • a sandbox dir whose final component is .ssh (host secret-dir component check)

Plus a positive test: an explicit allowed_mount_paths entry covering a .aws directory lets the mount succeed (audit-visible escape hatch).

All 35 realfs tests + 2286 lib tests pass. cargo fmt --check and cargo clippy --all-targets --features http_client,realfs -- -D warnings are green.


Generated by Claude Code

…lowlist

The default sensitive-path blocklist was too narrow (only /etc/shadow,
/etc/sudoers, /proc, /sys), so a misconfigured embedder could mount
broad host paths (/, /etc, /root, /Users, /home, /dev, /run, /var/run,
/boot, /private) or paths containing secret-bearing components
(.ssh, .aws, .kube, .docker, .gnupg, .gcloud) with a single mount call.

Refuse those paths by default. The mount still succeeds when the
embedder explicitly allowlists it via allowed_mount_paths(), turning
the trust-boundary break into an audit-visible decision instead of
silent permissiveness.

Closes #1549
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
bashkit c67e4a8 Commit Preview URL

Branch Preview URL
May 06 2026, 09:33 AM

@chaliy
chaliy merged commit e73fb34 into main May 6, 2026
34 checks passed
@chaliy
chaliy deleted the fix/issue-1549-realfs-allowlist branch May 6, 2026 09:45
chaliy added a commit that referenced this pull request May 30, 2026
…1557)

## Summary

The default sensitive-path blocklist for `RealFs` mounts only covered
four exact paths (`/etc/shadow`, `/etc/sudoers`, `/proc`, `/sys`).
Without an explicit `allowed_mount_paths` configuration, a misconfigured
embedder could mount broad host paths (`/`, `/etc`, `/root`, `/Users`,
`/home`, `/dev`, `/run`, `/var/run`, `/boot`, `/private`) or paths
containing secret-bearing components (`.ssh`, `.aws`, `.kube`,
`.docker`, `.gnupg`, `.gcloud`) with a single mount call — exposing
secrets, sockets, kernel state, and host configuration to sandboxed
scripts.

This PR refuses those paths by default. The mount still succeeds when
the embedder explicitly allowlists it via `allowed_mount_paths()`,
turning the trust-boundary break into an audit-visible decision instead
of silent permissiveness. Existing writable-mount warnings are preserved
as observational signal.

## Why

Closes #1549. New threat: TM-FS-013.

## How

- Replace the four-entry `SENSITIVE_MOUNT_PATHS` constant with a broader
prefix list.
- Add `SENSITIVE_PATH_COMPONENTS` for secret-bearing dir names checked
against every component of the canonicalized mount path (catches
`~/.ssh`, etc.).
- New `is_sensitive_mount_path()` helper. Treats `/` specially
(`starts_with` would match every path) and returns `true` if any
component matches a known secret name.
- When an allowlist is set, sensitive paths still go through the
allowlist check first — but allowlisted-and-sensitive paths now emit a
louder warning ("trust-boundary intentionally broken"). When no
allowlist is set, sensitive paths are refused.
- `specs/threat-model.md` gains a TM-FS-013 entry under TM-ESC-016.

## Tests

New regression tests in `tests/realfs_tests.rs` covering refusal of:

- `/`
- `/etc`
- `/dev`
- `/sys`
- a sandbox dir whose final component is `.ssh` (host secret-dir
component check)

Plus a positive test: an explicit `allowed_mount_paths` entry covering a
`.aws` directory lets the mount succeed (audit-visible escape hatch).

All 35 realfs tests + 2286 lib tests pass. `cargo fmt --check` and
`cargo clippy --all-targets --features http_client,realfs -- -D
warnings` are green.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01FUJR2V1kE75fLNdfWxD4iS)_
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.

security(realfs): make host mount policy allowlist-first

1 participant