SSH Execution Patterns¶
Overview¶
In a modern AI-automated infrastructure, SSH serves as the primary execution plane. This page documents the patterns and security models for allowing LLM-powered agents to interact with remote systems safely.
Architecture: The Three Planes¶
A robust automation stack separates concerns into three distinct layers:
- Reasoning Plane (LLM): The "Brain." It analyzes the current state and decides what needs to be done. It should never have direct access to SSH keys or credentials.
- Control Plane (Agent): The "Operator." A script or framework (Aider, OpenHands, Custom Python) that manages the loop, handles the LLM interaction, and initiates connections.
- Execution Plane (SSH): The "Hands." The actual remote system being managed. Access is strictly controlled and audited.
Execution Patterns¶
1. Tool-Based Execution¶
The agent is provided with a "tool" (function) like run_ssh_command(host, cmd).
- Workflow: Agent sends command to controller -> Controller executes via SSH library (e.g., Paramiko, Fabric) -> Output is returned to the agent.
- Best for: Dynamic, multi-step troubleshooting and complex configuration.
2. Wrapper Script Execution¶
The agent calls a local wrapper script (e.g., pi_exec "reboot") instead of raw SSH.
- Workflow: Agent executes a local command -> Local script handles SSH connection, logging, and pre-command validation.
- Best for: Restricting agents to a predefined set of safe operations.
3. Human-in-the-Loop (HITL)¶
Every command proposed by the LLM must be approved by a human before execution.
- Workflow: Agent proposes: rm -rf /var/log/* -> Controller waits for user input -> User approves/denies -> Loop continues.
- Best for: High-stakes production changes and learning phases.
Security Model¶
Dedicated Users¶
Never use the root user for AI-driven SSH. Create a dedicated service user (e.g., ai-agent) with the minimal set of permissions required for its task.
Restricted Sudoers¶
If the agent needs root privileges, use /etc/sudoers.d/ai-agent to restrict it to specific commands:
ai-agent ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/apt update
Command Allowlists¶
Implement a validation layer in your custom agent that checks proposed commands against a regex allowlist before they ever reach the SSH layer.
Why You NEVER Give SSH Keys to LLM Providers¶
Directly giving an SSH key to a cloud-based LLM provider (via a "plugin" or "action") creates a massive security hole. If the provider is compromised, or if a prompt injection attack occurs, the attacker has a direct path into your private infrastructure. Always keep the keys in your local Control Plane.
Threat Model¶
| Threat | Impact | Mitigation |
|---|---|---|
| Prompt Injection | Attacker tricks LLM into running malicious commands (e.g. rm -rf /). |
Human-in-the-loop, command allowlists, restricted sudo. |
| Hallucination | LLM invents a non-existent or destructive command. | Syntax validation, dry-run modes, standard error handling. |
| API Compromise | LLM provider API key is stolen. | The attacker can use your credits, but cannot access your servers because they don't have your SSH keys. |
| Controller Compromise | The machine running the agent is hacked. | Standard host hardening; the keys are here, so this is your most sensitive point. |
Logging and Auditing¶
- Local Logs: Capture every command sent and the full output in the agent's log.
- Remote Syslog: Use
auditdor standard syslog on the target machine to record all activity by theai-agentuser.