fix(security): block runtime config state edits
This commit is contained in:
committed by
Roman Tataurov
parent
d43ce63b4d
commit
a2fdf64a5e
@@ -1193,6 +1193,44 @@ impl SecurityPolicy {
|
||||
false
|
||||
}
|
||||
|
||||
fn runtime_config_dir(&self) -> Option<PathBuf> {
|
||||
let parent = self.workspace_dir.parent()?;
|
||||
Some(
|
||||
parent
|
||||
.canonicalize()
|
||||
.unwrap_or_else(|_| parent.to_path_buf()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_runtime_config_path(&self, resolved: &Path) -> bool {
|
||||
let Some(config_dir) = self.runtime_config_dir() else {
|
||||
return false;
|
||||
};
|
||||
if !resolved.starts_with(&config_dir) {
|
||||
return false;
|
||||
}
|
||||
if resolved.parent() != Some(config_dir.as_path()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let Some(file_name) = resolved.file_name().and_then(|value| value.to_str()) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
file_name == "config.toml"
|
||||
|| file_name == "config.toml.bak"
|
||||
|| file_name == "active_workspace.toml"
|
||||
|| file_name.starts_with(".config.toml.tmp-")
|
||||
|| file_name.starts_with(".active_workspace.toml.tmp-")
|
||||
}
|
||||
|
||||
pub fn runtime_config_violation_message(&self, resolved: &Path) -> String {
|
||||
format!(
|
||||
"Refusing to modify ZeroClaw runtime config/state file: {}. Use dedicated config tools or edit it manually outside the agent loop.",
|
||||
resolved.display()
|
||||
)
|
||||
}
|
||||
|
||||
pub fn resolved_path_violation_message(&self, resolved: &Path) -> String {
|
||||
let guidance = if self.allowed_roots.is_empty() {
|
||||
"Add the directory to [autonomy].allowed_roots (for example: allowed_roots = [\"/absolute/path\"]), or move the file into the workspace."
|
||||
@@ -2787,4 +2825,33 @@ mod tests {
|
||||
};
|
||||
assert!(!p.is_under_allowed_root("/any/path"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn runtime_config_paths_are_protected() {
|
||||
let workspace = PathBuf::from("/tmp/zeroclaw-profile/workspace");
|
||||
let policy = SecurityPolicy {
|
||||
workspace_dir: workspace.clone(),
|
||||
..SecurityPolicy::default()
|
||||
};
|
||||
let config_dir = workspace.parent().unwrap();
|
||||
|
||||
assert!(policy.is_runtime_config_path(&config_dir.join("config.toml")));
|
||||
assert!(policy.is_runtime_config_path(&config_dir.join("config.toml.bak")));
|
||||
assert!(policy.is_runtime_config_path(&config_dir.join(".config.toml.tmp-1234")));
|
||||
assert!(policy.is_runtime_config_path(&config_dir.join("active_workspace.toml")));
|
||||
assert!(policy.is_runtime_config_path(&config_dir.join(".active_workspace.toml.tmp-1234")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workspace_files_are_not_runtime_config_paths() {
|
||||
let workspace = PathBuf::from("/tmp/zeroclaw-profile/workspace");
|
||||
let policy = SecurityPolicy {
|
||||
workspace_dir: workspace.clone(),
|
||||
..SecurityPolicy::default()
|
||||
};
|
||||
let nested_dir = workspace.join("notes");
|
||||
|
||||
assert!(!policy.is_runtime_config_path(&workspace.join("notes.txt")));
|
||||
assert!(!policy.is_runtime_config_path(&nested_dir.join("config.toml")));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user