Skip to content

Feature: Granular control for bash command auto-approval in tool_approval plugin #114

@wu-changxing

Description

@wu-changxing

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-approve

Proposed:

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 False

2. 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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions