MCPcopy Create free account
hub / github.com/NVIDIA/OpenShell / validate_sandbox_policy

Function validate_sandbox_policy

crates/openshell-policy/src/lib.rs:1204–1323  ·  view source on GitHub ↗

Validate that a sandbox policy does not contain unsafe content. Returns `Ok(())` if the policy is safe, or `Err(violations)` listing all safety violations found. Callers decide how to handle violations (hard error vs. logged warning). Checks performed: - `run_as_user` / `run_as_group` must be "sandbox" - Filesystem paths must be absolute (start with `/`) - Filesystem paths must not contain `..`

(
    policy: &SandboxPolicy,
)

Source from the content-addressed store, hash-verified

1202/// - Total path count must not exceed [`MAX_FILESYSTEM_PATHS`]
1203/// - Network endpoint hosts must not use TLD wildcards (e.g. `*.com`)
1204pub fn validate_sandbox_policy(
1205 policy: &SandboxPolicy,
1206) -> std::result::Result<(), Vec<PolicyViolation>> {
1207 let mut violations = Vec::new();
1208
1209 // Check process identity — must be "sandbox" or a numeric UID/GID
1210 // within the acceptable sandbox range.
1211 // `ensure_sandbox_process_identity` should be called before this to
1212 // fill in defaults; any invalid value is rejected.
1213 if let Some(ref process) = policy.process {
1214 if !is_valid_sandbox_identity(&process.run_as_user) {
1215 violations.push(PolicyViolation::InvalidProcessIdentity {
1216 field: "run_as_user",
1217 value: process.run_as_user.clone(),
1218 });
1219 }
1220 if !is_valid_sandbox_identity(&process.run_as_group) {
1221 violations.push(PolicyViolation::InvalidProcessIdentity {
1222 field: "run_as_group",
1223 value: process.run_as_group.clone(),
1224 });
1225 }
1226 }
1227
1228 // Check filesystem paths
1229 if let Some(ref fs) = policy.filesystem {
1230 let total_paths = fs.read_only.len() + fs.read_write.len();
1231 if total_paths > MAX_FILESYSTEM_PATHS {
1232 violations.push(PolicyViolation::TooManyPaths { count: total_paths });
1233 }
1234
1235 for path_str in fs.read_only.iter().chain(fs.read_write.iter()) {
1236 if path_str.len() > MAX_PATH_LENGTH {
1237 violations.push(PolicyViolation::FieldTooLong {
1238 path: truncate_for_display(path_str),
1239 length: path_str.len(),
1240 });
1241 continue;
1242 }
1243
1244 let path = Path::new(path_str);
1245
1246 if !path.has_root() {
1247 violations.push(PolicyViolation::RelativePath {
1248 path: path_str.clone(),
1249 });
1250 }
1251
1252 if path
1253 .components()
1254 .any(|c| matches!(c, std::path::Component::ParentDir))
1255 {
1256 violations.push(PolicyViolation::PathTraversal {
1257 path: path_str.clone(),
1258 });
1259 }
1260 }
1261

Calls 5

truncate_for_displayFunction · 0.85
pushMethod · 0.80
lenMethod · 0.80
is_emptyMethod · 0.45