Refuse grant paths that cannot be mounted
Implemented-By: OpenCode session (model recorded in docs/implementer-log.md)
This commit is contained in:
@@ -260,6 +260,14 @@ fn check_grant(grant: &LoadedGrant, problems: &mut Vec<GrantProblem>) {
|
|||||||
None,
|
None,
|
||||||
format!("{:?} is not a valid absolute path", path),
|
format!("{:?} is not a valid absolute path", path),
|
||||||
);
|
);
|
||||||
|
} else if path.contains([':', ',']) {
|
||||||
|
// Mounted as `--volume=<path>:<path>:ro`, where both are separators.
|
||||||
|
push(
|
||||||
|
problems,
|
||||||
|
file.clone(),
|
||||||
|
None,
|
||||||
|
format!("{:?} cannot be mounted: it contains ':' or ','", path),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Rule 8: every host must be a valid host pattern.
|
// Rule 8: every host must be a valid host pattern.
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
//! A grant path is mounted into the tool container as `--volume=<path>:<path>:ro`, so a path with
|
||||||
|
//! `:` or `,` in it cannot be granted: the set is invalid, as for any other bad grant (M3b spec,
|
||||||
|
//! section 3). Do not edit.
|
||||||
|
|
||||||
|
#[path = "support/tmp.rs"]
|
||||||
|
mod tmp;
|
||||||
|
|
||||||
|
use brokerd::grants::load;
|
||||||
|
use tmp::TempDir;
|
||||||
|
|
||||||
|
fn grant_with_path(path: &str) -> String {
|
||||||
|
format!(
|
||||||
|
"tool = \"read_file\"\nmode = \"auto\"\nmax_taint = \"secret\"\n[constraints]\npaths = [{path:?}]\n"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn a_path_with_a_colon_or_a_comma_makes_the_set_invalid() {
|
||||||
|
for path in ["/home/kyle/a:b", "/home/kyle/a,b", "/x:/y", "/n,ro"] {
|
||||||
|
let dir = TempDir::new("mount-bad");
|
||||||
|
dir.write("notes.toml", &grant_with_path(path));
|
||||||
|
let problems = load(dir.path()).expect_err(path);
|
||||||
|
assert_eq!(problems.len(), 1, "{path}: {problems:?}");
|
||||||
|
assert_eq!(problems[0].file, "notes.toml");
|
||||||
|
assert!(
|
||||||
|
problems[0].problem.contains("cannot be mounted"),
|
||||||
|
"{path}: {}",
|
||||||
|
problems[0].problem
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn other_punctuation_is_still_fine() {
|
||||||
|
for path in [
|
||||||
|
"/home/kyle/a b",
|
||||||
|
"/home/kyle/a;b",
|
||||||
|
"/home/kyle/a=b",
|
||||||
|
"/home/kyle/a.b-c_d",
|
||||||
|
] {
|
||||||
|
let dir = TempDir::new("mount-ok");
|
||||||
|
dir.write("notes.toml", &grant_with_path(path));
|
||||||
|
assert!(load(dir.path()).is_ok(), "{path}");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -419,4 +419,5 @@ each task's commit. Three rows were malformed by the first run's orchestrator: t
|
|||||||
six cells, and its notes had been pasted into task 05's row; task 10's notes into task 11's; and
|
six cells, and its notes had been pasted into task 05's row; task 10's notes into task 11's; and
|
||||||
task 01's stopped row carried the notes of M2b task 11. Each is moved back or removed, with a
|
task 01's stopped row carried the notes of M2b task 11. Each is moved back or removed, with a
|
||||||
bracketed mark, and pipes inside code are escaped so every row has its eight cells.
|
bracketed mark, and pipes inside code are escaped so every row has its eight cells.
|
||||||
|
| M3b/03-brokerd-grant-mount-rule | 2026-09-22 | done | 1 | pass | none | Copied `tests/grants_mount.rs` from the plan's `files/`. Added a third arm to the path loop in `check_grant` (grants.rs:263), an `else if path.contains([':', ','])` checked only when the first two arms did not apply, reporting `"{:?} cannot be mounted: it contains ':' or ','"`. The `else if` chain means a path already reported as invalid is not reported twice. `cargo fmt --all` kept the `push` multi-line (the single-line form in the task exceeds 100 columns); the wording matches the task verbatim. Both suites pass (17 grants, 2 mount); `make gate` prints `gate: ok` on the first run. | ? |
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user