Back to skill

Security audit

Server Maintenance

Security checks for vulnerabilities and agentic risk

Overview

This skill is a server-maintenance helper, but it can run unconfirmed root SSH maintenance and cache deletion against hard-coded public servers.

Review carefully before installing or running. Do not run the batch or cron commands on production systems until targets are replaced with your own validated configuration, SSH host keys are pinned, root access is removed or tightly limited, and cleanup requires an explicit apply confirmation or dry-run review.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
check.sh:5
Finding
Unvalidated Server Host Permits Shell and SSH Argument Injection<![CDATA[ ## Vulnerability Details **File Location**: `check.sh:5-16, 20, 26, 34, 40`; `cleanup.sh:6-17, 21, 32, 36-52, 56` **Vulnerability Type**: Command and argument injection through an unvalidated host parameter **Risk Level**: High ### Complete Code Snippet From `check.sh`: ```bash SERVER_HOST="${1:-localhost}" SERVER_NAME="${2:-本地}" if [ "$SERVER_HOST" = "localhost" ]; then CMD_PREFIX="" else CMD_PREFIX="ssh root@$SERVER_HOST" fi $CMD_PREFIX df -h / | tail -1 if [ "$SERVER_HOST" = "localhost" ]; then du -h --max-depth=2 /root 2>/dev/null | sort -rh | head -8 else ssh root@$SERVER_HOST "du -h --max-depth=2 /root 2>/dev/null | sort -rh | head -8" fi if [ "$SERVER_HOST" = "localhost" ]; then find /root -type f -size +100M 2>/dev/null -exec du -h {} + | sort -rh | head -5 else ssh root@$SERVER_HOST "find /root -type f -size +100M 2>/dev/null -exec du -h {} + | sort -rh | head -5" fi $CMD_PREFIX free -h ``` From `cleanup.sh`: ```bash SERVER_HOST="${1:-localhost}" SERVER_NAME="${2:-本地}" DRY_RUN="${3:-false}" if [ "$SERVER_HOST" = "localhost" ]; then CMD_PREFIX="" else CMD_PREFIX="ssh root@$SERVER_HOST" fi $CMD_PREFIX df -h / | tail -1 $CMD_PREFIX "npm cache clean --force 2>&1 | grep -v 'npm warn'" $CMD_PREFIX " if [ -d ~/.cache/ms-playwright ]; then cd ~/.cache/ms-playwright LATEST=\$(ls -d chromium-* 2>/dev/null | sort -V | tail -1 | sed 's/chromium-//') if [ -n \"\$LATEST\" ]; then echo \"保留最新版本: \$LATEST\" for dir in chromium-* chromium_headless_shell-*; do if [[ \$dir != *\$LATEST* ]] && [ -d \"\$dir\" ]; then echo \"删除旧版本: \$dir\" rm -rf \"\$dir\" fi done fi fi " $CMD_PREFIX df -h / | tail -1 ``` ### Technical Analysis The scripts accept `SERVER_HOST` directly from the first positional argument and incorporate it into a command stored as a scalar string: ```bash CMD_PREFIX="ssh root@$SERVER_HOST" ``` The command ...[truncated 2296 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate `SERVER_HOST` before using it. Accept only a strict IPv4, IPv6, or DNS-name format and reject whitespace, control characters, shell metacharacters, leading hyphens, and embedded SSH options. 2. Do not store a command in a scalar string. Use a Bash array: ```bash if [ "$SERVER_HOST" = "localhost" ]; then df -h / else ssh_cmd=(ssh -- "root@$SERVER_HOST") "${ssh_cmd[@]}" df -h / fi ``` 3. Quote every host and destination expansion: ```bash ssh -- "root@$SERVER_HOST" "df -h /" ``` 4. Add an explicit allowlist of approved servers and fail closed when the host is not listed. 5. Use a restricted maintenance account instead of `root`. 6. Add automated tests with whitespace, wildcard, option-like, and malformed host values to verify that unsafe input is rejected. 7. Apply the same correction to both `check.sh` and `cleanup.sh`. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
maintain-all.sh:25
Finding
SSH Host-Key Verification Is Disabled for Root Maintenance Connections<![CDATA[ ## Vulnerability Details **File Location**: `maintain-all.sh:25-31` **Vulnerability Type**: Insecure SSH host authentication **Risk Level**: High ### Complete Code Snippet ```bash for server in "${SERVERS[@]}"; do IFS=':' read -r name host <<< "$server" # 获取清理前状态 BEFORE=$(ssh -o StrictHostKeyChecking=no root@$host "df -h / | tail -1 | awk '{print \$5}'") # 执行清理 ssh -o StrictHostKeyChecking=no root@$host "npm cache clean --force > /dev/null 2>&1" || true # 获取清理后状态 AFTER=$(ssh -o StrictHostKeyChecking=no root@$host "df -h / | tail -1 | awk '{print \$5}'") echo "| $name | $BEFORE | $AFTER | ✓ |" done ``` ### Technical Analysis Every SSH invocation in the batch-maintenance loop specifies: ```bash -o StrictHostKeyChecking=no ``` This configuration prevents SSH from requiring explicit trust confirmation for a previously unknown host key. Consequently, the automation does not establish a trustworthy association between the configured public IP address and the expected server key on first connection. The connection is made as `root`, which increases the severity. Although SSH authentication does not ordinarily disclose a private key directly, an impersonated endpoint can receive authentication attempts, collect connection metadata, present deceptive authentication flows, and receive the maintenance command if authentication succeeds through another configured mechanism. The script also provides no dedicated `UserKnownHostsFile` containing pre-provisioned keys, no host-key fingerprint validation, and no mechanism to stop maintenance when a target identity changes unexpectedly. ### Attack Path 1. An administrator invokes `maintain-all.sh` from a network where an attacker can intercept or redirect traffic, or DNS/routing infrastructure points the connection to an attacker-controlled system. 2. The script initiates an SSH connection to a public IP as `root`. 3. The attacker presents an untrusted SSH hos ...[truncated 1106 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `-o StrictHostKeyChecking=no`. 2. Provision the expected host keys before automation is enabled and enforce verification: ```bash ssh \ -o StrictHostKeyChecking=yes \ -o UserKnownHostsFile="$SCRIPT_DIR/known_hosts" \ -- "maintenance@$host" \ "df -h /" ``` 3. Store independently verified host-key fingerprints in a protected configuration-management system. 4. Treat host-key changes as fatal errors requiring administrator review. 5. Use a dedicated, least-privileged maintenance account rather than `root`. 6. Restrict the maintenance account's authorized key with suitable options, such as source-address restrictions and a forced command where operationally possible. 7. Use separate SSH keys for this task and prevent agent forwarding. 8. Add connection and command timeouts so unattended maintenance cannot hang indefinitely. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
maintain-all.sh:13
Finding
Batch Script Performs Unconfirmed Root Operations Against Hard-Coded Public Servers<![CDATA[ ## Vulnerability Details **File Location**: `maintain-all.sh:13-16, 22-31` **Vulnerability Type**: Excessive privilege and unsafe fixed-target automation **Risk Level**: High ### Complete Code Snippet ```bash # 定义服务器列表 declare -a SERVERS=( "中央:43.163.225.27" "东京:43.167.192.145" ) for server in "${SERVERS[@]}"; do IFS=':' read -r name host <<< "$server" # 获取清理前状态 BEFORE=$(ssh -o StrictHostKeyChecking=no root@$host "df -h / | tail -1 | awk '{print \$5}'") # 执行清理 ssh -o StrictHostKeyChecking=no root@$host "npm cache clean --force > /dev/null 2>&1" || true # 获取清理后状态 AFTER=$(ssh -o StrictHostKeyChecking=no root@$host "df -h / | tail -1 | awk '{print \$5}'") echo "| $name | $BEFORE | $AFTER | ✓ |" done ``` ### Technical Analysis The documented batch command automatically contacts two hard-coded public IP addresses and requests a `root` SSH session. It performs this action without asking the operator to confirm the targets and without providing a dry-run mode. The package includes `servers.json`, but `maintain-all.sh` does not read that configuration. Therefore, editing the documented server list does not change the actual targets used by the executable batch script. This creates a dangerous separation between the apparent configuration and effective behavior. Using `root` violates least-privilege principles because checking disk usage and cleaning a specific npm cache do not inherently require unrestricted administrative SSH access. Public IP ownership and infrastructure assignments can also change over time. A bundled fixed address can eventually identify a different system, while the script continues attempting root authentication and maintenance against it. ### Attack Path 1. A user installs the skill and invokes the documented `maintain-all.sh` command. 2. The script silently selects its embedded public IP addresses rather than reading the user-reviewed `servers.json` configuration. 3. ...[truncated 1210 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove all bundled public IP addresses from the executable script. 2. Load targets from a user-controlled, validated configuration file and clearly display the effective target list before connecting. 3. Require explicit confirmation for destructive batch operations. For unattended jobs, require a separate reviewed flag such as `--apply`. 4. Make dry-run behavior the default and provide a clear preview of every target and command. 5. Replace `root` with a dedicated maintenance account whose permissions are limited to the required cache directory and monitoring commands. 6. Scope npm cache cleanup to an explicitly configured user and cache path. 7. Verify ownership of every target and pin its SSH host key. 8. Remove `|| true` or capture failures accurately. Do not print a success symbol unless the cleanup command and verification both succeed. 9. Keep configuration and runtime behavior consistent by making `servers.json` the authoritative source or removing it if it is not supported. 10. Log the verified host identity, command result, and target address for each operation without logging credentials. ]]>
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 (13)

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The README instructs users to run cleanup and maintenance scripts on local and remote servers without any warning that these operations can change system state, remove files, or affect service availability. In a server-maintenance context, omission of safety warnings increases the chance of accidental destructive use, especially when operators may execute commands verbatim on production hosts.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The cron example promotes unattended weekly execution of server-maintenance scripts without warning that automated cleanup can run against production systems and continue making changes without human review. This is more dangerous in context because the skill is explicitly designed for multi-server administration, so a misconfiguration or unsafe script behavior could repeatedly impact several hosts.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The trigger phrase "检查磁盘" is broad enough to match routine administrative or diagnostic requests that may not imply consent for automated cleanup or multi-server maintenance actions. In this skill, that ambiguity is more dangerous because the documented functionality includes destructive or state-changing operations such as cache cleanup, remote SSH batch actions, and scheduled execution, increasing the chance of unintended invocation.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The script connects to a remote host as root and executes system inspection commands, which is a safety-relevant operation on a code file. While the file has brief comments, it provides no user-facing warning, confirmation, or explicit disclosure that it will initiate remote root SSH access when a non-local host is supplied.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The script’s header frames it as simple cache/temp cleanup, but it can execute destructive commands on a remote host as root via SSH based on a positional argument. That mismatch increases the chance an operator runs it against production infrastructure without understanding the privilege level and blast radius, leading to unintended deletion of remote caches and browser artifacts.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The script runs destructive cleanup commands locally or remotely, including rm -rf on versioned Playwright directories, without any confirmation prompt, explicit warning, or scoped safety checks. In a maintenance skill context, this is dangerous because a mistyped host or an unexpected cache layout can cause irreversible deletion on the wrong system, especially when executed as root over SSH.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script executes remote commands as root across multiple hardcoded servers and disables SSH host key verification with StrictHostKeyChecking=no. This makes it dangerous in context: an operator can trigger privileged changes on all hosts without confirmation, and the disabled host verification increases exposure to man-in-the-middle attacks against administrative SSH sessions.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The JSON uses Chinese-only natural-language values for server names and descriptions across the configuration. Because this file provides no opt-in, alternative locale, or documented justification that the skill is intended only for Chinese-speaking users, it creates a language/locale policy concern under the natural-language policy rule.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The natural-language content of the skill is presented in Chinese throughout, while also including English trigger phrases, but it does not state that the user can choose another language or locale. This creates a language policy concern because the skill appears to impose a specific language without opt-in.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
All user-facing strings in the script are in Chinese, and there is no option or documentation allowing the user to select another language. This is a natural-language policy concern because the skill imposes a specific language/locale without opt-in or stated regional justification.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
The script's comments, status messages, and default server name are in Chinese, making the skill effectively fixed to a specific language. There is no opt-in, language selection mechanism, or justification that this is intended only for a Chinese-language environment.

Intent-Code Divergence

Low
Confidence
89% confidence
Finding
The file header describes the script as 'Server Maintenance - Maintain All Servers' / '批量维护所有服务器', which implies general maintenance activity across servers. In reality, the implementation is narrowly limited to fetching root filesystem usage and running `npm cache clean --force` remotely via SSH. This is an intent/documentation mismatch because the comments overstate the script's actual operational scope.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
User-facing comments and terminal output are written in Chinese, and the script provides no option to select another language or indication that the tool is intentionally restricted to a Chinese-speaking environment. This can violate language/locale policy when skills are expected to avoid forcing a specific language without user opt-in.

Static analysis

No suspicious patterns detected.