-
Notifications
You must be signed in to change notification settings - Fork 98
Feature: Granular control for bash command auto-approval in tool_approval plugin #114
Description
Problem
Currently, the tool_approval plugin's auto-approve feature only supports tool-level control. When you add bash to the auto-approve list, it approves all bash commands, including potentially dangerous ones.
# Current limitation - all or nothing
agent = Agent(
"assistant",
tools=[bash],
auto_approve_tools=["bash"] # ❌ Approves EVERYTHING: ls, rm -rf, git push, etc.
)This forces users to choose between:
- ❌ Too permissive: Auto-approve all bash commands (dangerous)
- ❌ Too restrictive: Manually approve every single command (annoying)
Desired Feature
Add granular command and parameter control to auto-approval:
# Proposed syntax - granular control
agent = Agent(
"assistant",
tools=[bash],
auto_approve_tools={
"bash": {
"commands": ["git status", "git diff", "ls", "pwd"], # Exact commands
"patterns": [
r"^git log", # Regex patterns
r"^pytest.*--tb=short", # Allow specific flags
r"^npm run build"
],
"safe_prefixes": ["git status", "git log", "git diff"], # Prefix matching
"blocked_patterns": [r"rm -rf", r"git push.*--force"] # Explicitly block
}
}
)Use Cases
1. Safe git operations only
auto_approve_tools={
"bash": {
"commands": ["git status", "git diff", "git log"],
"blocked_patterns": [r"git push", r"git reset --hard", r"git clean -f"]
}
}2. Read-only file operations
auto_approve_tools={
"bash": {
"commands": ["ls", "pwd", "cat", "head", "tail"],
"patterns": [r"^grep", r"^find.*-name"],
"blocked_patterns": [r"rm", r"mv", r"cp"]
}
}3. Test commands only
auto_approve_tools={
"bash": {
"patterns": [
r"^pytest.*",
r"^npm test",
r"^python -m unittest"
]
}
}4. Directory-restricted operations
auto_approve_tools={
"bash": {
"patterns": [r"^cd /safe/path/"],
"validate": lambda cmd: "/safe/path/" in cmd # Custom validation
}
}Implementation Suggestions
1. Update tool_approval.py auto-approve check
Current code (simplified):
# In tool_approval.py
if tool_name in auto_approve_list:
return # Auto-approveProposed:
def should_auto_approve(tool_name: str, tool_args: dict, auto_approve_config) -> bool:
"""Check if tool execution should be auto-approved based on granular rules."""
if isinstance(auto_approve_config, list):
# Backward compatible: simple list of tool names
return tool_name in auto_approve_config
if isinstance(auto_approve_config, dict):
if tool_name not in auto_approve_config:
return False
rules = auto_approve_config[tool_name]
# For bash tool, check command
if tool_name == "bash":
command = tool_args.get("command", "")
# Check exact commands
if "commands" in rules and command in rules["commands"]:
return True
# Check patterns
if "patterns" in rules:
for pattern in rules["patterns"]:
if re.match(pattern, command):
return True
# Check safe prefixes
if "safe_prefixes" in rules:
for prefix in rules["safe_prefixes"]:
if command.startswith(prefix):
return True
# Check blocked patterns (explicit deny)
if "blocked_patterns" in rules:
for pattern in rules["blocked_patterns"]:
if re.search(pattern, command):
return False
# Custom validation function
if "validate" in rules and callable(rules["validate"]):
return rules["validate"](command)
# For other tools, just check if they're in the dict (simple approval)
return True
return False2. Backward Compatibility
# Old syntax still works
auto_approve_tools=["bash", "search", "write_file"]
# New syntax is opt-in
auto_approve_tools={
"bash": {"commands": ["git status"]},
"search": True, # Simple approval
"write_file": {"patterns": [r"^/tmp/.*"]} # Path restrictions
}3. Configuration Validation
Add validation to catch typos and invalid patterns:
def validate_auto_approve_config(config):
"""Validate auto_approve_tools configuration."""
if isinstance(config, dict):
for tool_name, rules in config.items():
if isinstance(rules, dict):
# Validate known keys
valid_keys = {"commands", "patterns", "safe_prefixes", "blocked_patterns", "validate"}
unknown_keys = set(rules.keys()) - valid_keys
if unknown_keys:
raise ValueError(f"Unknown auto-approve keys for '{tool_name}': {unknown_keys}")
# Validate regex patterns compile
for pattern_key in ["patterns", "blocked_patterns"]:
if pattern_key in rules:
for pattern in rules[pattern_key]:
try:
re.compile(pattern)
except re.error as e:
raise ValueError(f"Invalid regex pattern '{pattern}': {e}")Benefits
✅ Safety: Only approve specific safe commands
✅ Convenience: Auto-approve common read-only operations
✅ Flexibility: Regex patterns for complex matching
✅ Backward compatible: Existing code keeps working
✅ Explicit blocklist: Prevent dangerous operations even with broad patterns
✅ Custom validation: Lambda/function support for complex logic
Related
- Existing tool_approval docs:
docs/useful_plugins/tool_approval.md - Shell approval plugin:
connectonion/useful_plugins/shell_approval.py(similar pattern could be used)
Priority
Medium-High - This would significantly improve UX for automated agents while maintaining security.
Additional Ideas:
- Add dry-run mode to test what would be auto-approved
- Logging of auto-approved commands for audit trail
- Rate limiting on auto-approvals (max N auto-approvals per minute)
- Time-based rules (auto-approve only during working hours)