Skip to content

Commit d536278

Browse files
committed
fix(sandbox): allow non-directory read_write entries like /dev/null
The symlink guard incorrectly rejected all non-directory entries. Character devices like /dev/null are legitimate read_write paths used in sandbox policies. Only reject symlinks, which are the actual attack vector for the chown privilege escalation. Refs: #350
1 parent c14b694 commit d536278

1 file changed

Lines changed: 2 additions & 7 deletions

File tree

  • crates/openshell-sandbox/src

crates/openshell-sandbox/src/lib.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,20 +1208,15 @@ fn prepare_filesystem(policy: &SandboxPolicy) -> Result<()> {
12081208
// The TOCTOU window between lstat and chown is not exploitable because
12091209
// no untrusted process is running yet (the child has not been forked).
12101210
for path in &policy.filesystem.read_write {
1211-
// Check for symlinks or non-directory files before touching the path.
1211+
// Check for symlinks before touching the path. Character/block devices
1212+
// (e.g. /dev/null) are legitimate read_write entries and must be allowed.
12121213
if let Ok(meta) = std::fs::symlink_metadata(path) {
12131214
if meta.file_type().is_symlink() {
12141215
return Err(miette::miette!(
12151216
"read_write path '{}' is a symlink — refusing to chown (potential privilege escalation)",
12161217
path.display()
12171218
));
12181219
}
1219-
if !meta.file_type().is_dir() {
1220-
return Err(miette::miette!(
1221-
"read_write path '{}' exists but is not a directory — refusing to chown",
1222-
path.display()
1223-
));
1224-
}
12251220
} else {
12261221
debug!(path = %path.display(), "Creating read_write directory");
12271222
std::fs::create_dir_all(path).into_diagnostic()?;

0 commit comments

Comments
 (0)