Skip to content

Security: roman-ryzenadvanced/Z-Agent-Remote-Control

Security

docs/SECURITY.md

Security Documentation

Threat Model

Z-Agent Remote Control is designed to let an AI agent perform useful tasks on your computer (file operations, running commands, checking system info) while preventing destructive actions.

Trust Boundaries

┌───────────────────────────────────────────────────────┐
│  Untrusted Network (Internet)                        │
│  ┌─────────────────────────────────────────────────┐  │
│  │  AI Agent (could be any LLM service)            │  │
│  │  - Has the tunnel URL and API key               │  │
│  │  - Can send any JSON-RPC request                │  │
│  └──────────────┬──────────────────────────────────┘  │
│                 │ HTTPS (Cloudflare TLS)                 │
│  ┌──────────────▼──────────────────────────────────┐  │
│  │  Cloudflare Tunnel Edge                          │  │
│  │  - TLS termination                               │  │
│  │  - No access to request content                  │  │
│  └──────────────┬──────────────────────────────────┘  │
│                 │ HTTP (localhost only)                   │
│  ┌──────────────▼──────────────────────────────────┐  │
│  │  MCP Server (trusted boundary)                   │  │
│  │  Layer 1: Bearer token auth                       │  │
│  │  Layer 2: Command blocklist                       │  │
│  │  Layer 3: Path allowlist (file ops)               │  │
│  │  Layer 4: Subprocess timeout                      │  │
│  │  Layer 5: Audit logging                           │  │
└──────────────┬──────────────────────────────────┘  │
│                 │                                      │
│  ┌──────────────▼──────────────────────────────────┐  │
│  │  Local Filesystem (restricted to allowed dirs)   │  │
│  └─────────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────────┘

Security Layers

Layer 1: Authentication

Every request must include a valid Bearer token in the Authorization header.

Authorization: Bearer <api-key>
  • Keys are checked as constant-time string comparison
  • Missing or invalid keys return HTTP 401 with a JSON-RPC error
  • Default key is a placeholder — users must generate their own
  • Key generation uses secrets.choice() (crypto-secure RNG)

Layer 2: Command Blocklist

The run_command tool blocks any command containing these substrings:

Blocked Why
rm File deletion (even rm -rf /)
sudo Privilege escalation
shutdown System shutdown
reboot System reboot
halt System halt
mkfs Filesystem formatting
dd Disk destruction (dd if=/dev/zero)
chmod Permission changes
chown Ownership changes
kill Process termination
killall Mass process termination
pkill Pattern process termination

Implementation: Substring matching — any command string containing these patterns is rejected. This catches variations like sudo rm -rf / or /usr/bin/kill -9 1.

Known limitations:

  • Advanced attackers could potentially encode commands to bypass substring checks (e.g., base64 encoding)
  • The blocklist is a first line of defense, not a security boundary
  • For stronger isolation, consider running in a container or VM

Layer 3: Path Allowlist

File operations (read_file, write_file, delete_file, list_directory, search_files) are restricted to configured allowed directories.

Implementation:

  1. User-provided paths are expanded (~ → home dir)
  2. Resolved to absolute paths (Path.resolve())
  3. Checked against all allowed directory prefixes
  4. If the resolved path doesn't start with any allowed directory, the operation is rejected

Default allowed directory: ~/projects

Users can add more via the Security tab in Z Control.

Layer 4: Process Timeout

All run_command executions have a configurable timeout (default: 25 seconds). This prevents:

  • Long-running processes from hanging the server
  • Fork bombs and resource exhaustion
  • Network-bound commands from blocking indefinitely

Layer 5: Audit Logging

Every tool call is logged with:

  • Timestamp (ISO 8601)
  • Tool name
  • Arguments (truncated for large content)
  • Client IP
  • Result status

Log location: ~/.local/share/mimocode/mcp-audit.log

Review the audit log regularly from the Settings tab in Z Control.

Transport Security

Cloudflare Tunnel

  • All traffic between the AI agent and Cloudflare uses TLS 1.3
  • Cloudflare forwards to localhost over plain HTTP (loopback interface only)
  • The MCP server binds to 127.0.0.1 — not accessible from other machines on the LAN
  • No inbound firewall ports need to be opened

Tunnel URL Security

  • Tunnel URLs are ephemeral (change on every cloudflared restart)
  • Only someone with both the URL AND the API key can access the server
  • The URL alone is useless without the API key

Recommendations

For Users

  1. Always generate a strong API key — use the Generate New button in the Security tab. Aim for 16+ characters with mixed case, numbers, and symbols.

  2. Minimize allowed directories — only add directories that the AI agent needs to access. ~/projects is a good default sandbox.

  3. Kill services when not in use — click "Kill All & Lock Down" in the Control tab when you're done. This stops both the MCP server and tunnel.

  4. Review the audit log — periodically check the audit log in the Settings tab to see what commands have been executed.

  5. Never share your tunnel URL and API key — these are equivalent to full access to your allowed directories.

  6. Use auto-start wisely — only enable auto-start if you need the tunnel available immediately on login.

  7. Keep the app updated — check the GitHub repo for security updates.

For Advanced Users

  • Run the MCP server in a Docker container or VM for stronger isolation
  • Use a firewall to block all inbound connections except from the cloudflared process
  • Set up Cloudflare named tunnels (instead of quick tunnels) for persistent URLs with access policies
  • Consider fail2ban or similar to block repeated auth failures (the MCP server doesn't implement this)

Limitations

  • No rate limiting — the MCP server doesn't limit request frequency
  • No user management — single API key, no multi-user support
  • Substring blocklist can be bypassed — determined attackers could encode commands (e.g., Python one-liners with exec)
  • File content is logged — the audit log may contain file contents for write operations
  • No encryption at rest — the API key is stored in plaintext in settings.json
  • No revocation — changing the key requires restarting the MCP server

Reporting Security Issues

If you find a security vulnerability, please open a GitHub Issue with the [Security] tag. Do not publicly disclose the issue until a fix is available.

There aren't any published security advisories