feat(#1058): disallow built-in Bash; remove allowedBashPatterns; prompt sweep
This commit is contained in:
parent
013e8740bd
commit
88f22065b0
5 changed files with 16 additions and 87 deletions
|
|
@ -1898,13 +1898,13 @@ pub const SERVER_NAME: &str = "hyperhive";
|
|||
/// Built-in claude tools the turn loop enables via `--tools`. Anything not
|
||||
/// in this list literally doesn't exist in the session (claude won't even
|
||||
/// try to call it). Web egress (`WebFetch`/`WebSearch`) and nested agents
|
||||
/// (`Task`) are intentionally omitted for now; `Bash` is allowed pending a
|
||||
/// finer-grained allow-list system for shell command patterns. `TodoWrite`
|
||||
/// (`Task`) are intentionally omitted. `Bash` is disallowed — shell
|
||||
/// execution goes through `mcp__hyperhive__bash_run` (background tasks
|
||||
/// with structured output) instead of a raw interactive shell. `TodoWrite`
|
||||
/// is omitted because the todo list lives in claude's in-process session
|
||||
/// state and silently evaporates on /compact or session reset — agents
|
||||
/// should plan in /state notes instead. Edit later as our trust model
|
||||
/// evolves.
|
||||
pub const ALLOWED_BUILTIN_TOOLS: &[&str] = &["Bash", "Edit", "Glob", "Grep", "Read", "Write"];
|
||||
/// should plan in /state notes instead.
|
||||
pub const ALLOWED_BUILTIN_TOOLS: &[&str] = &["Edit", "Glob", "Grep", "Read", "Write"];
|
||||
|
||||
/// Which MCP tool surface to advertise via `--allowedTools`. The agent
|
||||
/// list is the strict subset of the manager list, so we just thread the
|
||||
|
|
@ -2032,27 +2032,12 @@ pub fn allowed_mcp_tools(groups: &[hive_sh4re::ToolGroup]) -> Vec<String> {
|
|||
}
|
||||
|
||||
/// Combined allow-list passed to `--allowedTools` (auto-approve) — covers
|
||||
/// both the built-ins and the MCP surface. If `hyperhive.allowedBashPatterns`
|
||||
/// is configured (non-empty list in `/etc/hyperhive/bash-allow.json`),
|
||||
/// `Bash` is replaced with one `Bash(pattern)` entry per pattern so
|
||||
/// only vetted command families auto-approve without a blanket shell grant.
|
||||
/// An empty or missing allow file keeps the current wholesale `Bash` entry.
|
||||
/// both the built-ins and the MCP surface.
|
||||
#[must_use]
|
||||
pub fn allowed_tools_arg(flavor: Flavor) -> String {
|
||||
let mut all: Vec<String> = ALLOWED_BUILTIN_TOOLS
|
||||
.iter()
|
||||
.flat_map(|s| {
|
||||
if *s == "Bash" {
|
||||
let patterns = load_bash_allow();
|
||||
if patterns.is_empty() {
|
||||
vec!["Bash".to_owned()]
|
||||
} else {
|
||||
patterns.into_iter().map(|p| format!("Bash({p})")).collect()
|
||||
}
|
||||
} else {
|
||||
vec![(*s).to_owned()]
|
||||
}
|
||||
})
|
||||
.map(|s| (*s).to_owned())
|
||||
.collect();
|
||||
let groups = effective_tool_groups(flavor);
|
||||
all.extend(allowed_mcp_tools(&groups));
|
||||
|
|
@ -2073,13 +2058,6 @@ pub fn builtin_tools_arg() -> String {
|
|||
ALLOWED_BUILTIN_TOOLS.join(",")
|
||||
}
|
||||
|
||||
/// Where the NixOS module writes the per-agent Bash command allow-list
|
||||
/// (see `nix/templates/harness-base.nix`). Contains a JSON array of
|
||||
/// command-pattern strings like `["git *", "ls *"]`. Empty array =
|
||||
/// wholesale `Bash` approval (the default). Non-empty = one
|
||||
/// `Bash(pattern)` entry per item in `--allowedTools`.
|
||||
const BASH_ALLOW_PATH: &str = "/etc/hyperhive/bash-allow.json";
|
||||
|
||||
/// Where the NixOS module writes the per-agent extra-MCP spec (see
|
||||
/// `nix/templates/harness-base.nix`). Each entry becomes an additional
|
||||
/// `mcpServers.<key>` block in the rendered claude config + a
|
||||
|
|
@ -2164,20 +2142,6 @@ fn default_allowed_tools() -> Vec<String> {
|
|||
/// Read + parse the Bash command allow-list. Returns an empty vec when
|
||||
/// the file is missing or unparsable (degrade to wholesale `Bash`
|
||||
/// approval — same as the pre-feature behaviour).
|
||||
fn load_bash_allow() -> Vec<String> {
|
||||
let Ok(raw) = std::fs::read_to_string(BASH_ALLOW_PATH) else {
|
||||
return Vec::new();
|
||||
};
|
||||
serde_json::from_str::<Vec<String>>(&raw).unwrap_or_else(|e| {
|
||||
tracing::warn!(
|
||||
path = BASH_ALLOW_PATH,
|
||||
error = ?e,
|
||||
"bash-allow list parse failed; falling back to wholesale Bash approval",
|
||||
);
|
||||
Vec::new()
|
||||
})
|
||||
}
|
||||
|
||||
/// Read + parse the extra-MCP spec. Returns an empty map when
|
||||
/// the file is missing or unparsable (the agent has none configured,
|
||||
/// or the file is malformed — both cases degrade to "no extra servers").
|
||||
|
|
|
|||
Loading…
Reference in a new issue