fix: confine MCP agents' files to allowed folders; recovery discard deletes only recovery entries (#205) (#578)
Agent tool calls (MCP, and bridged control requests carrying allow_paths) reach files only in the open design's folder (strictly inside home or the temporary folder, not in a hidden folder, and never its hidden files), the app's recovery folder, the server's private scratch folder and each --allow-path; --allow-any-path lifts the limit. Paths are resolved first, so .. and symlinks that lead out (including a save through a link, #845) are refused. On Windows, UNC, device, NT, verbatim non-drive, drive-relative, alternate-stream, reserved-device and 8.3 short-name paths are refused before any file system call, and the resolved path must be on a local drive. doc.recovery_discard and doc.recover {discard} delete only real recovery entries. Docs: mcp.md, control-protocol.md, README.
This commit is contained in:
1 parent
3d3f9b626f
commit
96f6424aec
23 files changed
+1000
-37
No files matched your search
@@ -136,6 +136,15 @@ fn motion_study_plays_and_exports() {
|
||||
run(&mut s, "motion.export", json!({"study": "Push", "samples": 3, "path": csv.to_string_lossy()}));
|
||||
let text = std::fs::read_to_string(&csv).unwrap();
|
||||
assert!(text.starts_with("step,occurrence,x,y,z") && text.lines().count() == 1 + 3 * 2, "{text}");
|
||||
// For an agent (#205) the export lands only inside its folders.
|
||||
let root = dir.join("root");
|
||||
std::fs::create_dir_all(&root).unwrap();
|
||||
solidcraft_io::vfs::scoped(Some(solidcraft_io::vfs::PathScope::new([root.clone()])), || {
|
||||
run(&mut s, "motion.export", json!({"study": "Push", "samples": 2, "path": root.join("in.json").to_string_lossy()}));
|
||||
let e = s.execute("motion.export", &json!({"study": "Push", "samples": 2, "path": dir.join("out.json").to_string_lossy()})).unwrap_err();
|
||||
assert!(e.to_string().contains("outside the folders this agent may use"), "{e}");
|
||||
});
|
||||
assert!(root.join("in.json").exists() && !dir.join("out.json").exists());
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
assert!(s.execute("motion.study", &json!({"keys": [{"joint": "Rail", "index": 3, "points": [[0, 1]]}]})).is_err());
|
||||
run(&mut s, "motion.delete", json!({"study": "Push"}));
|
||||
|
||||
Reference in new issue
Block a user