Back to skill

Security audit

Hostinger VPS MCP Tools

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent VPS deployment skill, but it uses unsafe root-level deployment defaults that could expose or compromise a server.

Review and harden the scripts before running them on a real VPS. Pin and verify installers, validate all ports/names/domains/keys, keep SSH host-key checking enabled, avoid public XRDP/webchat exposure by default, remove passwordless full sudo and Docker access from the runtime account, avoid root SSH key login, and treat any saved Hostinger or integration token as sensitive infrastructure access.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
Findings (14)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/03-install-docker.sh:12
Finding
Docker Installer Executes Mutable Remote Code as Root<![CDATA[ ## Vulnerability Details **File Location**: `scripts/03-install-docker.sh:12-16` **Vulnerability Type**: Remote payload retrieval and immediate execution **Risk Level**: Critical ### Vulnerable Code ```sh # Remove old versions echo "[1/4] Removing old Docker versions..." apt-get remove -y docker docker-engine docker.io containerd runc 2>/dev/null || true # Install Docker using official script echo "[2/4] Installing Docker..." curl -fsSL https://get.docker.com | sh ``` ### Technical Analysis The script is intended to run as root and pipes an HTTP response directly into `sh`. The retrieved payload is not pinned to a reviewed version and is not authenticated using a separately verified signature or checksum. Although `get.docker.com` is Docker's official convenience endpoint, the effective code can change after this Skill has been reviewed. Compromise of the upstream service, DNS resolution, TLS trust chain, or delivery infrastructure would permit arbitrary root-level payload substitution. ### Attack Path 1. An administrator invokes `03-install-docker.sh` as root. 2. The script requests the current contents of `https://get.docker.com`. 3. An upstream or network trust compromise supplies modified shell code. 4. The response is sent directly to `sh` without inspection or verification. 5. The substituted payload executes with unrestricted root privileges. ### Impact Assessment Successful exploitation provides complete control of the VPS, including the ability to read credentials, alter SSH configuration, access agent data, install persistent services, modify containers, and compromise all users. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Install Docker from its signed APT repository instead of using `curl | sh`. - Pin the Docker packages to approved versions. - Install and verify the repository signing key through an authenticated process. - If a remote script is unavoidable, download it separately, verify a pinned cryptographic digest or detached signature, and inspect it before execution. - Record the exact version and checksum in the Skill so the audited artifact cannot change silently. ]]>

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/security/setup-tailscale.sh:13
Finding
Tailscale Installer Executes Mutable Remote Code as Root<![CDATA[ ## Vulnerability Details **File Location**: `scripts/security/setup-tailscale.sh:13-15` **Vulnerability Type**: Remote payload retrieval and immediate execution **Risk Level**: Critical ### Vulnerable Code ```sh # Install Tailscale echo "[1/3] Installing Tailscale..." curl -fsSL https://tailscale.com/install.sh | sh ``` ### Technical Analysis This optional security script is explicitly designed to run as root. It immediately executes mutable content returned by Tailscale's installer endpoint without pinning a release or verifying an artifact signature or checksum. The endpoint is legitimate, but trusting a mutable remote script expands the trusted computing base beyond the audited Skill and gives any successful upstream compromise direct root execution. ### Attack Path 1. The administrator runs the Tailscale setup script as root. 2. The script downloads the current installer response. 3. A compromised upstream endpoint or network trust component returns a modified script. 4. The modified response is executed immediately by `sh`. 5. The payload gains unrestricted control of the server. ### Impact Assessment The payload would execute as root and could steal secrets, manipulate VPN routing, alter firewall rules, install persistent services, or take over the OpenClaw deployment. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Configure Tailscale's signed package repository using a pinned repository key. - Install a specifically approved package version through APT. - Do not execute network responses directly in a shell. - Where package installation cannot be used, verify a pinned checksum and signature before executing a downloaded artifact. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/deploy-all.sh:29
Finding
Deployment Arguments Are Interpolated into a Root Remote Shell Command<![CDATA[ ## Vulnerability Details **File Location**: `scripts/deploy-all.sh:29-35` **Vulnerability Type**: Remote command injection **Risk Level**: Critical ### Vulnerable Code ```sh run_remote() { local script="$1" shift echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "Running: $(basename "$script") $*" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" ssh $SSH_OPTS root@"$SERVER_IP" "bash -s $*" < "$script" echo "" } ``` The vulnerable function is later called with user-controlled values: ```sh run_remote "$SCRIPT_DIR/04-deploy-koda.sh" "$KODA_PORT" run_remote "$SCRIPT_DIR/05-configure-identity.sh" "$AGENT_NAME" ``` ### Technical Analysis After `shift`, all remaining arguments are expanded through `$*` into a single remote command string. The local double quotes do not protect the resulting value from parsing by the remote shell. Shell metacharacters included in an argument, particularly `AGENT_NAME`, can terminate or extend `bash -s ...` and execute additional commands. The SSH session runs as `root`, so injected commands inherit full administrative privileges. ### Attack Path 1. An attacker influences a deployment argument, such as the agent name. 2. The value contains shell control syntax, for example a semicolon followed by another command. 3. `run_remote` concatenates the value into `"bash -s $*"`. 4. The remote SSH shell parses the injected syntax. 5. The additional command executes as root on the VPS. ### Impact Assessment Exploitation permits arbitrary root command execution, including credential theft, account creation, firewall modification, persistence installation, or complete destruction of the target VPS. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Do not construct remote shell commands by concatenating input. - Validate ports as decimal integers in the range `1-65535`. - Restrict agent names to an explicitly approved character set and length. - Pass arguments through a safely encoded channel, or quote every argument using a rigorously tested mechanism such as `printf '%q'`. - Prefer copying a fixed script and a structured JSON configuration, then parse the configuration without shell evaluation. - Add tests using whitespace, quotes, semicolons, command substitutions, and newline characters. ]]>

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/deploy-all.sh:23
Finding
SSH Host Authentication Is Explicitly Disabled During Root Deployment<![CDATA[ ## Vulnerability Details **File Location**: `scripts/deploy-all.sh:23-26,39-42` **Vulnerability Type**: SSH endpoint spoofing **Risk Level**: High ### Vulnerable Code ```sh # SSH options SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p $SSH_PORT" if [ -n "$SSH_KEY" ]; then SSH_OPTS="$SSH_OPTS -i $SSH_KEY" fi ``` ```sh # For first connection, use default port 22 FIRST_SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" if [ -n "$SSH_KEY" ]; then FIRST_SSH_OPTS="$FIRST_SSH_OPTS -i $SSH_KEY" fi ``` ### Technical Analysis `StrictHostKeyChecking=no` accepts an untrusted host key, while `UserKnownHostsFile=/dev/null` prevents persistent detection of host-key changes. The deployment therefore has no cryptographic assurance that the SSH endpoint is the Hostinger VPS intended by the operator. Because root setup scripts and potentially an SSH private key are used during the connection, endpoint spoofing has severe consequences. ### Attack Path 1. An attacker redirects the target IP route, DNS resolution, or local network traffic to an attacker-controlled SSH server. 2. The attacker presents any SSH host key. 3. The deployment accepts it without warning or verification. 4. Root deployment scripts are transmitted to the spoofed server. 5. The attacker captures deployment content and may attempt credential or key-related attacks. ### Impact Assessment This can disclose deployment scripts and operational parameters, direct configuration to the wrong server, and undermine the authenticity of the entire provisioning process. The attack occurs across a root-administration trust boundary. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Obtain the VPS host-key fingerprint from a trusted Hostinger API or console channel. - Store the verified key in a deployment-specific `known_hosts` file. - Use `StrictHostKeyChecking=yes`. - Abort on host-key changes. - Do not place SSH option strings in an unquoted scalar; use a Bash array for options and validate the identity-file path. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/01-server-setup.sh:39
Finding
Koda Account Receives Unrestricted Passwordless Root Access<![CDATA[ ## Vulnerability Details **File Location**: `scripts/01-server-setup.sh:39-52` **Vulnerability Type**: Excessive privilege assignment **Risk Level**: Critical ### Vulnerable Code ```sh # Create koda user echo "[3/6] Creating 'koda' user..." if ! id "koda" &>/dev/null; then useradd -m -s /bin/bash -G sudo koda # Generate random password KODA_PASS=$(openssl rand -base64 12) echo "koda:$KODA_PASS" | chpasswd echo "" echo "⚠️ Generated password for 'koda' user: $KODA_PASS" echo "⚠️ Save this! Change with: passwd koda" echo "" fi # Allow koda user to sudo without password (for automation) echo "koda ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/koda ``` ### Technical Analysis The account used for the GUI, agent workspace, and routine administration is placed in the `sudo` group and granted `NOPASSWD:ALL`. This makes any code execution as `koda` equivalent to immediate root compromise. Unrestricted sudo is not minimally necessary to run the agent, access its workspace, or use XRDP. It defeats isolation between the externally accessible application account and the host operating system. ### Attack Path 1. An attacker compromises the `koda` account through XRDP credentials, an agent vulnerability, or local code execution. 2. The attacker runs any command using `sudo`. 3. Sudo performs no password or command restriction check. 4. The attacker obtains an unrestricted root shell. ### Impact Assessment The attacker gains complete control of the VPS and all stored secrets, containers, SSH configuration, firewall rules, users, and agent data. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Remove `NOPASSWD:ALL`. - Do not add the runtime account to the general `sudo` group. - If automation requires elevated operations, create a narrow sudoers allowlist for fixed root-owned scripts with immutable paths and arguments. - Separate deployment, service, GUI, and agent runtime accounts. - Validate sudoers changes with `visudo -cf` before installation. - Disable interactive login for service-only accounts. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/03-install-docker.sh:22
Finding
Docker Group Membership Grants the Agent Account Root-Equivalent Control<![CDATA[ ## Vulnerability Details **File Location**: `scripts/03-install-docker.sh:22-28` **Vulnerability Type**: Privilege escalation through Docker daemon access **Risk Level**: Critical ### Vulnerable Code ```sh # Add koda user to docker group echo "[4/4] Adding 'koda' user to docker group..." usermod -aG docker koda # Enable Docker service systemctl enable docker systemctl start docker ``` ### Technical Analysis Members of the Docker group can control the root-owned Docker daemon. Such a user can start a privileged container or mount the host root filesystem, making Docker group membership effectively equivalent to root access. The agent runtime account does not need permanent control of the Docker daemon merely to use an already deployed container. ### Attack Path 1. An attacker obtains command execution as `koda`. 2. The attacker asks Docker to start a container with the host filesystem mounted. 3. The container modifies host files or enters the host namespace. 4. The attacker obtains effective root control of the VPS. ### Impact Assessment The compromise extends from the agent account to all host files, secrets, processes, containers, and security controls. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Do not add `koda` to the Docker group. - Manage the container through a root-owned systemd unit or a narrowly scoped deployment service. - Consider rootless Docker or Podman where operationally appropriate. - Restrict access to the Docker socket and monitor all attempted access. - Keep application runtime identities separate from container-administration identities. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/01-server-setup.sh:63
Finding
Privileged Services Are Publicly Exposed by Default<![CDATA[ ## Vulnerability Details **File Location**: `scripts/01-server-setup.sh:63-70` **Vulnerability Type**: Unsafe network exposure **Risk Level**: High ### Vulnerable Code ```sh # Configure firewall echo "[5/6] Configuring firewall..." ufw default deny incoming ufw default allow outgoing ufw allow $SSH_PORT/tcp # SSH ufw allow 3389/tcp # XRDP ufw allow $KODA_PORT/tcp # Koda webchat ufw --force enable ``` The application is also bound externally in `scripts/04-deploy-koda.sh:32-35`: ```yaml restart: unless-stopped ports: - "${KODA_PORT}:18789" ``` ### Technical Analysis XRDP and the OpenClaw gateway are opened to every source address immediately during the default deployment. Private VPN or tunnel lockdown is an optional later step. The XRDP account is also configured with root-equivalent sudo and Docker privileges, making public exposure especially dangerous. A non-default port does not provide meaningful access control. ### Attack Path 1. An attacker scans the public VPS address. 2. Ports 3389 and the configured Koda port are reachable. 3. The attacker targets XRDP credentials or a vulnerability in the web-facing gateway. 4. Successful account or application compromise yields access as `koda`. 5. Passwordless sudo or Docker control escalates access to root. ### Impact Assessment The exposed attack surface can lead from unauthenticated internet access to agent compromise and ultimately full VPS control. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Bind the Koda service to `127.0.0.1` or a private VPN address by default. - Restrict XRDP and SSH firewall rules to explicitly trusted source networks. - Deploy and verify Tailscale, WireGuard, or a protected Cloudflare Tunnel before opening application access. - Require authentication and TLS at the application boundary. - Remove the `koda` account's root-equivalent privileges. - Make public exposure an explicit opt-in operation with a clear confirmation. ]]>

T08 · Insecure Dependencies

Error
Location
scripts/04-deploy-koda.sh:45
Finding
OpenClaw Container Build Uses Mutable and Unpinned Sources<![CDATA[ ## Vulnerability Details **File Location**: `scripts/04-deploy-koda.sh:45-59` **Vulnerability Type**: Unpinned container and source dependencies **Risk Level**: High ### Vulnerable Code ```dockerfile FROM node:22-slim RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* RUN corepack enable WORKDIR /app # Clone and build OpenClaw RUN git clone --depth 1 https://github.com/openclaw/openclaw.git . && \ pnpm install --frozen-lockfile && \ pnpm build && \ pnpm ui:build || true && \ rm -rf .git ``` ### Technical Analysis `node:22-slim` is a mutable image tag, and the Git clone retrieves the current repository head rather than an audited commit. `--frozen-lockfile` constrains package resolution but does not authenticate the repository contents or base image. The build is initiated by root through the Docker daemon. Upstream install and build hooks execute during image creation. ### Attack Path 1. The base-image tag or OpenClaw repository is compromised or changes unexpectedly. 2. A new deployment retrieves the mutable content. 3. Malicious package or build logic executes during `docker compose build`. 4. The resulting image contains attacker-controlled software. 5. The compromised agent receives access to persistent configuration and workspace volumes. ### Impact Assessment The attacker may control the deployed agent, steal API credentials stored in its configuration volume, alter responses, access workspace data, or attempt further attacks through the Docker build environment. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Pin the Node image by immutable digest. - Pin OpenClaw to a reviewed commit hash or signed release tag. - Verify release signatures or checksums before building. - Retain an auditable software bill of materials. - Fail the build if any required build stage fails; reconsider `pnpm ui:build || true`. - Scan the resulting image and dependencies before deployment. ]]>

T08 · Insecure Dependencies

Error
Location
scripts/security/setup-cloudflare-tunnel.sh:13
Finding
Cloudflared Is Downloaded from an Unverified Mutable Latest Release<![CDATA[ ## Vulnerability Details **File Location**: `scripts/security/setup-cloudflare-tunnel.sh:13-17` **Vulnerability Type**: Unverified executable dependency **Risk Level**: High ### Vulnerable Code ```sh # Install cloudflared echo "[1/3] Installing cloudflared..." curl -fsSL https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o /tmp/cloudflared.deb dpkg -i /tmp/cloudflared.deb rm /tmp/cloudflared.deb ``` ### Technical Analysis The script retrieves the mutable `latest` package and installs it as root without verifying an expected version, checksum, package signature, or detached release signature. HTTPS provides transport protection but does not protect against a compromised upstream release or account. ### Attack Path 1. An attacker compromises the upstream release asset or delivery account. 2. The `latest` URL points to an attacker-modified Debian package. 3. The deployment downloads and installs the package as root. 4. Package maintainer scripts or binaries execute with administrative privileges. 5. The subsequently enabled service provides persistence. ### Impact Assessment A malicious package can fully compromise the VPS and establish a persistent root service. The legitimate `cloudflared` service itself is necessary for the declared tunnel feature; the issue is unverified package installation. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Pin an approved cloudflared release version. - Verify Cloudflare's published checksum or signature before installation. - Prefer a signed package repository with controlled version selection. - Download to a directory created with `mktemp -d` and fail securely on any verification error. - Do not enable or start the service until artifact verification succeeds. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/security/lockdown-public.sh:22
Finding
Shell-Sourceable Root Configuration Contains Unvalidated Deployment Input<![CDATA[ ## Vulnerability Details **File Location**: `scripts/security/lockdown-public.sh:22-30` **Vulnerability Type**: Root command execution through unsafe configuration sourcing **Risk Level**: Critical ### Vulnerable Code ```sh # Remove Koda port from firewall echo "[1/3] Removing Koda webchat from public firewall..." ufw delete allow 18789/tcp 2>/dev/null || true # Get all custom Koda ports from config if [ -f /etc/koda/config ]; then source /etc/koda/config if [ -n "$KODA_PORT" ] && [ "$KODA_PORT" != "18789" ]; then ufw delete allow ${KODA_PORT}/tcp 2>/dev/null || true fi fi ``` The sourced file is created from unvalidated arguments in `scripts/01-server-setup.sh:95-97`: ```sh mkdir -p /etc/koda echo "KODA_PORT=$KODA_PORT" > /etc/koda/config echo "SSH_PORT=$SSH_PORT" >> /etc/koda/config ``` ### Technical Analysis `source` treats the data file as executable shell code. Since port arguments are not validated before being written, crafted shell syntax can be persisted in `/etc/koda/config`. Running the lockdown script later evaluates that syntax as root. Even if the current deployment interface normally supplies numeric ports, the script itself does not enforce this security boundary. ### Attack Path 1. An attacker or unsafe automation supplies a crafted Koda or SSH port value. 2. `01-server-setup.sh` writes the value verbatim into `/etc/koda/config`. 3. An administrator later runs `lockdown-public.sh` as root. 4. The script sources `/etc/koda/config`. 5. Embedded shell syntax executes with root privileges. ### Impact Assessment Successful exploitation provides arbitrary root command execution and can remain dormant in the configuration until the lockdown operation is invoked. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Never source files that are intended to contain data. - Validate both ports as decimal integers in the range `1-65535` before any use. - Store configuration as JSON or another non-executable format. - Parse only explicitly recognized keys and reject all malformed content. - Write configuration atomically with root ownership and mode `0600` or `0644` as appropriate. - Quote firewall arguments and use `ufw allow proto tcp from ... to any port "$KODA_PORT"` style invocation. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/security/setup-wireguard.sh:7
Finding
WireGuard Client Name Permits Root Path and Configuration Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/security/setup-wireguard.sh:7-27` **Vulnerability Type**: Unsanitized input in privileged file paths **Risk Level**: High ### Vulnerable Code ```sh CLIENT_NAME="${1:-client1}" WG_PORT=51820 ``` ```sh cd /etc/wireguard umask 077 wg genkey | tee server_private.key | wg pubkey > server_public.key wg genkey | tee ${CLIENT_NAME}_private.key | wg pubkey > ${CLIENT_NAME}_public.key SERVER_PRIVATE=$(cat server_private.key) SERVER_PUBLIC=$(cat server_public.key) CLIENT_PRIVATE=$(cat ${CLIENT_NAME}_private.key) CLIENT_PUBLIC=$(cat ${CLIENT_NAME}_public.key) ``` The same value is later used in another root-owned path: ```sh cat > /etc/wireguard/${CLIENT_NAME}.conf << EOF ``` ### Technical Analysis `CLIENT_NAME` is used unquoted and without validation in filenames under `/etc/wireguard`. Whitespace, glob characters, option-like content, or traversal components can change command parsing or target unintended paths. It is also inserted into generated configuration comments. The restrictive `umask 077` appropriately protects generated key material, but it does not prevent path manipulation. ### Attack Path 1. An attacker controls or influences `CLIENT_NAME`. 2. The supplied name contains path separators, shell word-splitting characters, or wildcard syntax. 3. Root-run `tee`, redirection, or `cat` operations resolve unintended arguments or paths. 4. Files outside the expected client namespace may be created or overwritten. 5. WireGuard subsequently consumes attacker-influenced configuration. ### Impact Assessment Depending on the supplied value and filesystem state, exploitation may overwrite root-controlled files, corrupt VPN configuration, disclose generated material, or disrupt networking. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Require `CLIENT_NAME` to match a strict expression such as `^[A-Za-z0-9_-]{1,64}$`. - Reject dots, slashes, whitespace, shell metacharacters, and leading hyphens. - Quote every filename expansion. - Construct paths under a fixed directory and verify the canonical path remains inside that directory. - Refuse to overwrite existing client files without explicit confirmation. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/security/setup-https.sh:7
Finding
Unvalidated HTTPS Inputs Are Embedded in Root-Owned Nginx Configuration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/security/setup-https.sh:7-42` **Vulnerability Type**: Configuration injection **Risk Level**: High ### Vulnerable Code ```sh DOMAIN="${1:?Usage: $0 DOMAIN EMAIL [KODA_PORT]}" EMAIL="${2:?Usage: $0 DOMAIN EMAIL [KODA_PORT]}" KODA_PORT="${3:-18789}" ``` ```sh cat > /etc/nginx/sites-available/koda << EOF server { listen 80; server_name $DOMAIN; location / { proxy_pass http://127.0.0.1:$KODA_PORT; proxy_http_version 1.1; proxy_set_header Upgrade \$http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto \$scheme; proxy_read_timeout 86400; } } EOF ``` ### Technical Analysis The domain and port are copied directly into an Nginx configuration generated as root. A value containing Nginx delimiters may introduce additional directives or alter proxy behavior. The port is also not constrained to a valid numeric TCP port. `nginx -t` checks syntax, but it does not determine whether syntactically valid injected directives are authorized. ### Attack Path 1. An attacker influences `DOMAIN` or `KODA_PORT`. 2. The value contains valid Nginx syntax that terminates or extends the intended directive. 3. The script writes the resulting configuration as root. 4. `nginx -t` accepts the syntactically valid injected configuration. 5. Nginx reloads with attacker-influenced routing or content behavior. ### Impact Assessment Exploitation can redirect traffic, expose unintended local services, alter virtual-host handling, or cause denial of service. The exact impact depends on the injected Nginx directives and installed modules. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Validate `DOMAIN` against strict DNS hostname rules and reject whitespace, braces, semicolons, and control characters. - Validate `KODA_PORT` as an integer from `1` through `65535`. - Validate the email address before passing it to Certbot. - Generate configuration from trusted templates using safely validated scalar values. - Review the rendered configuration and run `nginx -T` in a controlled validation step before activation. - Restore the previous configuration automatically if reload fails. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/security/setup-ssh-keys.sh:8
Finding
Unvalidated Public Key Is Granted Direct Root SSH Access<![CDATA[ ## Vulnerability Details **File Location**: `scripts/security/setup-ssh-keys.sh:8-34` **Vulnerability Type**: Excessive authorization and administrative lockout risk **Risk Level**: High ### Vulnerable Code ```sh PUBLIC_KEY="${1:?Usage: $0 \"ssh-rsa AAAA... user@host\"}" ``` ```sh # Add key to root mkdir -p /root/.ssh chmod 700 /root/.ssh echo "$PUBLIC_KEY" >> /root/.ssh/authorized_keys chmod 600 /root/.ssh/authorized_keys # Add key to koda user mkdir -p /home/koda/.ssh chmod 700 /home/koda/.ssh echo "$PUBLIC_KEY" >> /home/koda/.ssh/authorized_keys chmod 600 /home/koda/.ssh/authorized_keys chown -R koda:koda /home/koda/.ssh # Disable password authentication echo "[*] Disabling password authentication..." sed -i 's/^#*PasswordAuthentication .*/PasswordAuthentication no/' /etc/ssh/sshd_config sed -i 's/^#*ChallengeResponseAuthentication .*/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config sed -i 's/^#*UsePAM .*/UsePAM no/' /etc/ssh/sshd_config sed -i 's/^#*PermitRootLogin .*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config # Restart SSH systemctl restart sshd ``` ### Technical Analysis The script grants the supplied key access to both `root` and `koda` without validating the key format or confirming its fingerprint. It then disables password authentication and restarts SSH before proving that the intended administrator can authenticate. The SSH key operations are related to the declared hardening feature, but direct root authorization exceeds the minimum privileges needed. ### Attack Path 1. An attacker substitutes their public key in the script invocation or deployment input. 2. The script appends it to `/root/.ssh/authorized_keys`. 3. Root key login remains permitted through `PermitRootLogin prohibit-password`. 4. The attacker authenticates directly as root. 5. Alternatively, malformed or incorrect key input combined with disabled password authentication locks out the legitimate administrator. ### Impact Assessment A substi ...[truncated 129 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Validate the supplied key with `ssh-keygen` before installation. - Display and require confirmation of the key fingerprint. - Authorize the key only for a non-root administrative account. - Set `PermitRootLogin no`. - Use a temporary second SSH session to verify key authentication before disabling passwords. - Validate the SSH configuration with `sshd -t` before restarting. - Install keys idempotently and reject duplicate or malformed entries. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup-mcp-integrations.sh:21
Finding
Pipedream Bearer Token Is Persisted Without Explicit File Permission Hardening<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup-mcp-integrations.sh:21-47` **Vulnerability Type**: Plaintext credential storage with inherited permissions **Risk Level**: Medium ### Vulnerable Code ```sh # Create config directory mkdir -p "$(dirname "$MCP_CONFIG")" # Initialize config cat > "$MCP_CONFIG" << 'EOF' { "servers": {} } EOF ``` ```sh # Add Pipedream if provided if [ -n "$PIPEDREAM_KEY" ]; then echo "[3/3] Configuring Pipedream MCP..." mcporter config add pipedream \ --url "https://api.pipedream.com/v1/connect/mcp" \ --header "Authorization: Bearer $PIPEDREAM_KEY" \ --config "$MCP_CONFIG" echo " ✓ Pipedream connected" else echo "[3/3] Skipping Pipedream (no API key provided)" fi ``` ### Technical Analysis The bearer token is passed to `mcporter` for persistence in the MCP configuration. The script does not establish `umask 077`, explicitly apply mode `0600`, or use a secret-reference mechanism. The actual readability depends on the invoking process's umask and `mcporter` behavior, but the script does not enforce a safe permission boundary. ### Attack Path 1. The script is run under a permissive umask. 2. `mcporter` stores the authorization header in `mcporter.json`. 3. Another local account reads the configuration file. 4. The account extracts the Pipedream bearer token. 5. The token is reused against the configured integration endpoint. ### Impact Assessment Exposure may grant access to the Pipedream resources and external actions authorized by the token. Scope depends on the token's server-side permissions. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Set `umask 077` before creating any credential-bearing file. - Explicitly set the configuration file to mode `0600`. - Store the token in a credential vault and place only a secret reference in the MCP configuration. - Avoid passing secrets on command lines where they may be visible in process listings. - Use a least-privilege, short-lived token and document rotation and revocation procedures. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (103)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill claims to automate VPS provisioning and deployment, but the content shown is largely documentation and command examples rather than self-contained, bounded automation. This mismatch can cause an agent or user to trust the skill with high-impact actions without clear disclosure of what it actually modifies locally versus remotely, including credential storage and config changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill claims to automate VPS provisioning and deployment, but the content shown is largely documentation and command examples rather than self-contained, bounded automation. This mismatch can cause an agent or user to trust the skill with high-impact actions without clear disclosure of what it actually modifies locally versus remotely, including credential storage and config changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The skill claims to automate VPS provisioning and deployment, but the content shown is largely documentation and command examples rather than self-contained, bounded automation. This mismatch can cause an agent or user to trust the skill with high-impact actions without clear disclosure of what it actually modifies locally versus remotely, including credential storage and config changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill claims to automate VPS provisioning and deployment, but the content shown is largely documentation and command examples rather than self-contained, bounded automation. This mismatch can cause an agent or user to trust the skill with high-impact actions without clear disclosure of what it actually modifies locally versus remotely, including credential storage and config changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill claims to automate VPS provisioning and deployment, but the content shown is largely documentation and command examples rather than self-contained, bounded automation. This mismatch can cause an agent or user to trust the skill with high-impact actions without clear disclosure of what it actually modifies locally versus remotely, including credential storage and config changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill claims to automate VPS provisioning and deployment, but the content shown is largely documentation and command examples rather than self-contained, bounded automation. This mismatch can cause an agent or user to trust the skill with high-impact actions without clear disclosure of what it actually modifies locally versus remotely, including credential storage and config changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The skill claims to automate VPS provisioning and deployment, but the content shown is largely documentation and command examples rather than self-contained, bounded automation. This mismatch can cause an agent or user to trust the skill with high-impact actions without clear disclosure of what it actually modifies locally versus remotely, including credential storage and config changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill claims to automate VPS provisioning and deployment, but the content shown is largely documentation and command examples rather than self-contained, bounded automation. This mismatch can cause an agent or user to trust the skill with high-impact actions without clear disclosure of what it actually modifies locally versus remotely, including credential storage and config changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill claims to automate VPS provisioning and deployment, but the content shown is largely documentation and command examples rather than self-contained, bounded automation. This mismatch can cause an agent or user to trust the skill with high-impact actions without clear disclosure of what it actually modifies locally versus remotely, including credential storage and config changes.

Credential Access

High
Category
Privilege Escalation
Content
- **Auth**: Bearer token via `API_TOKEN` env var
- **Transport**: stdio (default) or HTTP streaming

**Important:** The API token is stored in `~/.openclaw/secrets.json` (the vault), **not** in plaintext in mcporter config. A `SecretRef` points to the vault key `HOSTINGER_API_TOKEN`.

### Key API Endpoints
Confidence
87% confidence
Finding
The skill documents persistent storage of a high-value Hostinger API token in a local secrets file and indicates use via environment variables. Any process, misconfiguration, backup leak, or local compromise affecting that file can lead to unauthorized VPS management actions, including provisioning, starting, stopping, and password resets.

Credential Access

High
Category
Privilege Escalation
Content
### Vault Storage

The Hostinger API token is stored in **`~/.openclaw/secrets.json`** under the key `HOSTINGER_API_TOKEN`. It is **never stored in plaintext** in mcporter.json — only a `SecretRef` pointer is stored there.

### Post-Deployment Hardening
Confidence
86% confidence
Finding
This repeats the documented persistence of the Hostinger API token in a local file. Because the token grants control over hosted infrastructure, local secret compromise can translate directly into account misuse and destructive cloud actions.

Credential Access

High
Category
Privilege Escalation
Content
- Consider headless mode if GUI not needed

**MCP tools not loading?**
- Verify token is saved: check `~/.openclaw/secrets.json` for `HOSTINGER_API_TOKEN`
- Run: `API_TOKEN=your-token mcporter list hostinger-api`
Confidence
95% confidence
Finding
The troubleshooting guidance tells the operator to check the secrets file directly and demonstrates passing the API token on the command line through an environment assignment. Both patterns increase the risk of credential disclosure through shell history, process inspection, screen sharing, logs, or copied terminal transcripts.

Credential Access

High
Category
Privilege Escalation
Content
const HOSTINGER_SERVER_NAME = "hostinger-api";
const HOSTINGER_CONFIG_PATH = path.join(os.homedir(), ".openclaw", "workspace", "config", "hostinger.json");
const VAULT_PATH = path.join(os.homedir(), ".openclaw", "secrets.json");
const VAULT_KEY = "HOSTINGER_API_TOKEN";

function readVault(): Record<string, string> {
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
if (!config) config = { mcpServers: {}, imports: [] };
      if (!config.mcpServers) config.mcpServers = {};

      // Store token in vault (secrets.json) — not plaintext in mcporter
      writeVaultToken(apiToken);

      // mcporter entry uses a SecretRef so the plaintext isn't duplicated
Confidence
87% confidence
Finding
The code persists the Hostinger API token in a plaintext JSON secrets file under the user's home directory. Even with mode 0600, plaintext at-rest storage increases exposure to local compromise, backups, sync tools, malware, and accidental disclosure; this is especially sensitive because the skill is for VPS administration and the token likely grants infrastructure access.

Missing User Warnings

High
Confidence
98% confidence
Finding
The configured view renders the Hostinger API token directly inside a code element, exposing a sensitive credential in plaintext to anyone with UI access, screen-sharing visibility, logs, screenshots, or browser inspection. In this skill context, that token may grant control over VPS, billing, and other Hostinger account resources, making exposure especially dangerous.

Ssd 3

High
Confidence
99% confidence
Finding
Displaying the configured API token in normal UI text is a direct secret-exposure issue. Because this skill is for Hostinger VPS deployment and management, compromise of the token could enable unauthorized infrastructure changes, password resets, instance lifecycle actions, and possibly broader account operations depending on token scope.

Chaining Abuse

High
Category
Tool Misuse
Content
# Install Docker using official script
echo "[2/4] Installing Docker..."
curl -fsSL https://get.docker.com | sh

# Install Docker Compose plugin
echo "[3/4] Installing Docker Compose..."
Confidence
98% confidence
Finding
Using 'curl ... | sh' removes any inspection boundary between untrusted network content and root command execution. In a provisioning script for internet-connected VPS hosts, this is especially dangerous because compromise of the fetched content immediately becomes full-system compromise.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
echo "[1/3] Installing cloudflared..."
curl -fsSL https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o /tmp/cloudflared.deb
dpkg -i /tmp/cloudflared.deb
rm /tmp/cloudflared.deb

# Install as service with token
echo "[2/3] Configuring tunnel..."
Confidence
95% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
EOF

ln -sf /etc/nginx/sites-available/koda /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t && systemctl reload nginx

# Open port 80 and 443
Confidence
95% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Credential Access

High
Category
Privilege Escalation
Content
# Add key to root
mkdir -p /root/.ssh
chmod 700 /root/.ssh
echo "$PUBLIC_KEY" >> /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys

# Add key to koda user
Confidence
90% confidence
Finding
Appending an arbitrary caller-supplied key to /root/.ssh/authorized_keys grants persistent remote login to the root account. In a deployment skill this is especially dangerous because any mistaken, spoofed, or attacker-provided key becomes full administrative access and may be hard to notice later.

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Content
#!/bin/bash
# Configure SSH Key-Only Authentication
# Usage: ./setup-ssh-keys.sh "ssh-rsa AAAA... user@host"
# Run as root

set -e

PUBLIC_KEY="${1:?Usage: $0 \"ssh-rsa AAAA... user@host\"}"

echo "🔐 Setting up SSH Key Authentication"
echo "====================================="

# Add key to root
mkdir -p /root/.ssh
chmod 700 /root/.ssh
echo "$PUBLIC_KEY" >> /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys

# Add key to koda user
mkdir -p /home/koda/.ssh
chmod 700 /home/koda/.ssh
echo "$PUBLIC_KEY" >> /home/koda/.ssh/authorized_keys
chmod 600 /home/koda/.ssh/authorized_keys
chown -R koda:koda /home/koda/.ssh

# Disable password authentication
echo "[*] Disabling password authentication..."
sed -i 's/^#*PasswordAuthentication .*/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/^#*ChallengeResponseAuthentication .*/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config
sed -i 's/^#*UsePAM .*/UsePAM n
Confidence
90% confidence
Finding
The YARA hit is triggered because the script injects a provided SSH key into both root and user authorized_keys, which is a known persistence technique used by attackers. In this administrative context the likely intent is benign setup, but the combination of root key installation and password-login disablement makes operator mistakes or supply-chain abuse particularly impactful.

Credential Access

High
Category
Privilege Escalation
Content
mkdir -p /root/.ssh
chmod 700 /root/.ssh
echo "$PUBLIC_KEY" >> /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys

# Add key to koda user
mkdir -p /home/koda/.ssh
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
mkdir -p /root/.ssh
chmod 700 /root/.ssh
echo "$PUBLIC_KEY" >> /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys

# Add key to koda user
mkdir -p /home/koda/.ssh
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
# Add key to koda user
mkdir -p /home/koda/.ssh
chmod 700 /home/koda/.ssh
echo "$PUBLIC_KEY" >> /home/koda/.ssh/authorized_keys
chmod 600 /home/koda/.ssh/authorized_keys
chown -R koda:koda /home/koda/.ssh
Confidence
90% confidence
Finding
Appending a supplied key to /home/koda/.ssh/authorized_keys creates persistent access for that account. In context this is an intended setup action, but it is still security-sensitive because an untrusted or incorrect key would silently authorize future remote access.

Credential Access

High
Category
Privilege Escalation
Content
# Add key to koda user
mkdir -p /home/koda/.ssh
chmod 700 /home/koda/.ssh
echo "$PUBLIC_KEY" >> /home/koda/.ssh/authorized_keys
chmod 600 /home/koda/.ssh/authorized_keys
chown -R koda:koda /home/koda/.ssh
Confidence
90% confidence
Finding
Appending a supplied key to /home/koda/.ssh/authorized_keys creates persistent access for that account. In context this is an intended setup action, but it is still security-sensitive because an untrusted or incorrect key would silently authorize future remote access.

Static analysis

No suspicious patterns detected.