mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-11 02:19:56 -06:00
Plug-ins: only a person can approve a plug-in's permissions and heavy budget
`plugin.install` accepted `grant` and `allowHeavy` from any client, so the program installing a plug-in could answer its own permission prompt. The desktop app now shows an approval dialog that names the module, its hash and what it asks for. Confirming it gives the engine a one-use approval tied to that module id, hash and permission list. A control or MCP request and a frame of synthetic input cannot confirm the dialog, and Enter does not confirm it. Without such an approval, `grant` and `allowHeavy` are refused. The new `--allow-plugin-grants` flag on `mcp` and `run` lets a person who starts a headless session accept them from requests. The flag cannot be combined with `--connect`. A module already approved in the desktop app still installs through its stored grant.
This commit is contained in:
@@ -19,6 +19,31 @@ fn empty_dir(dir: std::path::PathBuf) -> std::path::PathBuf {
|
||||
dir
|
||||
}
|
||||
|
||||
/// `run` refuses `plugin.install`'s `grant` unless the process was started with
|
||||
/// `--allow-plugin-grants`, which `mcp` won't take with `--connect`.
|
||||
#[test]
|
||||
fn plugin_grants_need_the_start_up_flag() {
|
||||
let module = vectorcraft_format::base64_encode(include_bytes!("../../../../crates/plugins/tests/fixtures/desaturate.wasm"));
|
||||
let steps = tmp("grants.json");
|
||||
std::fs::write(&steps, json!([{"command": "plugin.install", "params": {"dataBase64": module, "grant": ["doc.read"]}}]).to_string()).unwrap();
|
||||
let config = empty_dir(std::env::temp_dir().join(format!("vectorcraft-cli-test-grants-{}", std::process::id())));
|
||||
let run = |extra: &[&str]| {
|
||||
Command::new(BIN).env("VECTORCRAFT_CONFIG_DIR", &config).args(["run", "--commands", steps.to_str().unwrap()]).args(extra).output().unwrap()
|
||||
};
|
||||
let out = run(&[]);
|
||||
assert!(!out.status.success());
|
||||
let shown = String::from_utf8_lossy(&out.stderr).into_owned() + &String::from_utf8_lossy(&out.stdout);
|
||||
assert!(shown.contains("--allow-plugin-grants"), "{shown}");
|
||||
let out = run(&["--allow-plugin-grants"]);
|
||||
assert!(out.status.success(), "{}", String::from_utf8_lossy(&out.stderr));
|
||||
|
||||
let out = Command::new(BIN).args(["mcp", "--allow-plugin-grants", "--connect", "127.0.0.1:1"]).output().unwrap();
|
||||
assert!(!out.status.success());
|
||||
assert!(String::from_utf8_lossy(&out.stderr).contains("--allow-plugin-grants applies to the headless server"));
|
||||
let usage = Command::new(BIN).arg("help").output().unwrap();
|
||||
assert!(String::from_utf8_lossy(&usage.stdout).contains("--allow-plugin-grants lets plugin.install's grant and allowHeavy take effect"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn commands_prints_catalogue() {
|
||||
let out = Command::new(BIN).arg("commands").output().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user