Back to skill

Security audit

VM Health Check

Security checks for vulnerabilities and agentic risk

Overview

This VM-check skill is mostly coherent, but it should be reviewed before install because it uses unsafe SSH handling, persists connection metadata, and can run remote Docker cleanup.

Install only if you are comfortable with this skill accessing a remote Docker host over SSH and storing the VM host, username, and SSH key path in TOOLS.md. Before use, the publisher should fix SSH argument construction, restore host-key verification, validate config values, and require explicit confirmation for cleanup actions.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 ยท Insecure Skill Coding Practices

Error
Location
scripts/vm-check.sh:16
Finding
SSH Option Injection Through Unquoted Command Construction## Vulnerability Details **File Location**: `scripts/vm-check.sh:16-28` **Vulnerability Type**: SSH option injection and potential local command execution **Risk Level**: High ```bash SSH_KEY="${SSH_KEY:-~/.ssh/id_rsa}" VM_HOST="${VM_HOST:?VM_HOST is required. Set it via: VM_HOST=<host> bash vm-check.sh}" VM_USER="${VM_USER:-ubuntu}" SECTION="${1:-all}" SSH_CMD="ssh -i $SSH_KEY -o StrictHostKeyChecking=no $VM_USER@$VM_HOST" run_section() { local name="$1" local cmd="$2" echo "=== $name ===" $SSH_CMD "$cmd" 2>/dev/null echo "" } ``` The same unsafe expansion pattern is also used for direct SSH calls at lines 69, 82, 96, 99, and 100. ### Technical Analysis The script constructs an SSH invocation as a scalar string and subsequently expands `$SSH_CMD` without quotes. Bash performs word splitting and pathname expansion on this value. Consequently, whitespace and option-like content supplied through `SSH_KEY`, `VM_USER`, or `VM_HOST` can become additional arguments to the local `ssh` process. This is particularly dangerous because OpenSSH supports options such as `ProxyCommand`, which can cause a local process to be launched. An attacker who can influence the saved VM configuration or the environment passed to the script could place additional SSH options in one of these values. The script performs no validation to ensure that the key is a single path, that the username and hostname have valid syntax, or that injected options are rejected. Although the Skill requires SSH access for its declared VM-checking functionality, accepting arbitrary SSH arguments is not necessary and exceeds the minimum safe behavior. ### Attack Path 1. An attacker influences a VM configuration value stored in `TOOLS.md`, or otherwise controls an environment variable such as `SSH_KEY`. 2. The Agent extracts that value and passes it to `vm-check.sh`. 3. The value includes whitespace followed by an additional SSH op ...[truncated 1043 chars]
Remediation
## Remediation Suggestions Construct the SSH command as a Bash array so that every value remains exactly one argument: ```bash SSH_KEY="${SSH_KEY:-$HOME/.ssh/id_rsa}" SSH_CMD=( ssh -i "$SSH_KEY" -o StrictHostKeyChecking=yes -- "$VM_USER@$VM_HOST" ) run_section() { local name="$1" local cmd="$2" echo "=== $name ===" "${SSH_CMD[@]}" "$cmd" echo } ``` Apply the array form to every SSH invocation rather than expanding a command string. In addition: - Validate `VM_USER` against the syntax allowed for expected remote usernames. - Validate `VM_HOST` as a hostname, IPv4 address, or IPv6 address and reject whitespace, control characters, and leading hyphens. - Require `SSH_KEY` to resolve to an expected regular file and reject newline or control characters. - Use `$HOME/.ssh/id_rsa` rather than a literal tilde inside parameter expansion. - Treat values recovered from `TOOLS.md` as untrusted configuration rather than shell-safe text. - Preserve SSH errors or report them safely instead of suppressing all diagnostics with `2>/dev/null`.

T09 ยท Insecure Skill Coding Practices

Warning
Location
scripts/vm-check.sh:21
Finding
SSH Host Authentication Disabled## Vulnerability Details **File Location**: `scripts/vm-check.sh:21` **Vulnerability Type**: Missing SSH server identity verification **Risk Level**: Medium ```bash SSH_CMD="ssh -i $SSH_KEY -o StrictHostKeyChecking=no $VM_USER@$VM_HOST" ``` ### Technical Analysis `StrictHostKeyChecking=no` instructs SSH to accept previously unknown host keys automatically and weakens protection when identifying the remote endpoint. This prevents the Skill from reliably establishing that it is communicating with the intended VM. SSH authentication is required by the declared functionality, but disabling server identity validation is not. Secure host-key verification can be retained without granting the Skill additional privileges. ### Attack Path 1. The Agent initiates an SSH connection to the configured VM. 2. An attacker with control over DNS, routing, the local network, or the target address redirects the connection to an impersonating SSH server. 3. The attacker presents an untrusted host key. 4. Because strict host-key checking is disabled, the connection may proceed without meaningful identity confirmation. 5. The Skill sends its remote health-check or Docker command to the impersonating endpoint. 6. The attacker observes operational requests and returns fabricated output that the Agent may present as genuine VM status. ### Impact Assessment An attacker may learn the configured username, connection timing, and the administrative commands requested by the Skill. They may also falsify system-health, database-size, container, disk-usage, or cleanup results. Public-key authentication ordinarily does not transmit the private key itself, so this setting alone does not disclose the key file. The principal impacts are loss of endpoint authenticity, exposure of operational metadata, and compromised integrity of audit results.
Remediation
## Remediation Suggestions - Remove `StrictHostKeyChecking=no` and use standard SSH host-key verification. - Provision the expected VM key in a dedicated `known_hosts` file before running checks. - For first-time enrollment, display and require confirmation of the host-key fingerprint through a trusted channel. - If automatic first connection is required, use `StrictHostKeyChecking=accept-new`; this is weaker than pre-provisioning but safer than unconditional acceptance. - Consider specifying a dedicated file with `UserKnownHostsFile` to isolate Skill-managed hosts without weakening the user's global SSH configuration. - Treat host-key changes as security errors and stop rather than silently continuing.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill is presented as a health-check/reporting tool, but its documented behavior includes cleanup actions and references behavior not disclosed in the user-facing description, including SSH-related handling. That mismatch is dangerous because users may invoke it expecting read-only diagnostics while the underlying workflow can modify remote Docker state or weaken trust assumptions around remote access.

Credential Access

High
Category
Privilege Escalation
Content
# Configure via environment variables:
#   VM_HOST   - VM IP or hostname (required)
#   VM_USER   - SSH username (default: ubuntu)
#   SSH_KEY   - Path to SSH private key (default: ~/.ssh/id_rsa)
#
# Example:
#   VM_HOST=10.0.0.1 VM_USER=ubuntu SSH_KEY=~/.ssh/mykey bash vm-check.sh
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Configure via environment variables:
#   VM_HOST   - VM IP or hostname (required)
#   VM_USER   - SSH username (default: ubuntu)
#   SSH_KEY   - Path to SSH private key (default: ~/.ssh/id_rsa)
#
# Example:
#   VM_HOST=10.0.0.1 VM_USER=ubuntu SSH_KEY=~/.ssh/mykey bash vm-check.sh
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# Configure via environment variables:
#   VM_HOST   - VM IP or hostname (required)
#   VM_USER   - SSH username (default: ubuntu)
#   SSH_KEY   - Path to SSH private key (default: ~/.ssh/id_rsa)
#
# Example:
#   VM_HOST=10.0.0.1 VM_USER=ubuntu SSH_KEY=~/.ssh/mykey bash vm-check.sh
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
A skill advertised for health checks should not silently bundle destructive cleanup operations, because operators may trigger it during routine inspection and unintentionally delete images or caches needed for rollback or debugging. Even if some prune operations are commonly considered low risk, they still change system state and can disrupt operations when unexpectedly executed.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The trigger phrases are broad enough to match common administrative language, increasing the chance that the skill runs in contexts where the user only wanted general advice, not remote access or potentially mutating actions. In an environment with automatic tool selection, ambiguous triggers can cause unintended execution against production systems.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill instructs the agent to persist SSH connection details, including the private key path, in `TOOLS.md` without warning about sensitivity, access scope, or retention. Persisting infrastructure access metadata in a general project file can expose internal hosts and credential locations to other tools, collaborators, or future prompts that read that file.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest says the first run asks for VM details once, saves them, and never asks again. This script instead requires configuration through environment variables, hard-fails if VM_HOST is unset, and contains no prompting or persistence logic, so the implemented behavior does not match the advertised workflow.

Missing User Warnings

Medium
Confidence
99% confidence
Finding
The SSH command disables host key verification with `-o StrictHostKeyChecking=no`, which makes man-in-the-middle attacks materially easier. Because this skill connects to remote infrastructure and can run privileged Docker and database inspection commands, trusting any presented host key can expose credentials, infrastructure metadata, and enable command interception or redirection.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The script includes destructive cleanup actions (`docker image prune -af` and `docker builder prune -f`) in a skill primarily presented as a VM health-check tool. In this context, users may reasonably expect read-only diagnostics, so bundling state-changing operations increases the chance of accidental disruption, removal of cached artifacts, and operational impact on the remote host.

Intent-Code Divergence

Low
Confidence
88% confidence
Finding
The documentation says 'Never run `docker system prune -af` without explicit user approval (destroys volumes)'. However, `docker system prune -af` does not remove volumes unless `--volumes` is also specified, so the comment misstates what the command actually does. This is an intent/documentation divergence that could mislead operators about the command's real impact.

Static analysis

No suspicious patterns detected.