mirror of
https://github.com/instructkr/claw-code.git
synced 2026-04-07 00:24:50 +08:00
feat(runtime+tools): PermissionEnforcer — permission mode enforcement layer
Add PermissionEnforcer in crates/runtime/src/permission_enforcer.rs and wire enforce_permission_check() into crates/tools/src/lib.rs. Runtime additions: - PermissionEnforcer: wraps PermissionPolicy with enforcement API - check(tool, input): validates tool against active mode via policy.authorize() - check_file_write(path, workspace_root): workspace boundary enforcement - ReadOnly: deny all writes - WorkspaceWrite: allow within workspace, deny outside - DangerFullAccess/Allow: permit all - Prompt: deny (no prompter available) - check_bash(command): read-only command heuristic (60+ safe commands) - Detects -i/--in-place/redirect operators as non-read-only - is_within_workspace(): string-prefix boundary check - is_read_only_command(): conservative allowlist of safe CLI commands Tool wiring: - enforce_permission_check() public API for gating execute_tool() calls - Maps EnforcementResult::Denied to Err(reason) for tool dispatch 9 new tests covering all permission modes + workspace boundary + bash heuristic.
This commit is contained in:
@@ -14,6 +14,7 @@ use runtime::{
|
||||
edit_file, execute_bash, glob_search, grep_search, load_system_prompt,
|
||||
lsp_client::LspRegistry,
|
||||
mcp_tool_bridge::McpToolRegistry,
|
||||
permission_enforcer::{EnforcementResult, PermissionEnforcer},
|
||||
read_file,
|
||||
task_registry::TaskRegistry,
|
||||
team_cron_registry::{CronRegistry, TeamRegistry},
|
||||
@@ -872,6 +873,21 @@ pub fn mvp_tool_specs() -> Vec<ToolSpec> {
|
||||
]
|
||||
}
|
||||
|
||||
/// Check permission before executing a tool. Returns Err with denial reason if blocked.
|
||||
pub fn enforce_permission_check(
|
||||
enforcer: &PermissionEnforcer,
|
||||
tool_name: &str,
|
||||
input: &Value,
|
||||
) -> Result<(), String> {
|
||||
let input_str = serde_json::to_string(input).unwrap_or_default();
|
||||
let result = enforcer.check(tool_name, &input_str);
|
||||
|
||||
match result {
|
||||
EnforcementResult::Allowed => Ok(()),
|
||||
EnforcementResult::Denied { reason, .. } => Err(reason),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute_tool(name: &str, input: &Value) -> Result<String, String> {
|
||||
match name {
|
||||
"bash" => from_value::<BashCommandInput>(input).and_then(run_bash),
|
||||
|
||||
Reference in New Issue
Block a user