Back to skill

Security audit

OpenClaw VPS Server Hardening

Security checks for vulnerabilities and agentic risk

Overview

This skill is aimed at VPS hardening, but its root-level script has unsafe execution and lockout risks that users should review before installing.

Install only if you are comfortable auditing and modifying a root-level VPS hardening script. Use provider console access or backups, verify a non-root sudo account and SSH key before applying changes, avoid passing untrusted script arguments, and do not embed Cloudflare service-token secrets in a shipped mobile app.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/harden.sh:34
Finding

Root Command Injection Through Unvalidated SSH Port

Content
View full analysis
/tmp/root-command-output #' ``` 3. The value is stored without validation in `SSH_PORT` ...[truncated 815 chars]
Remediation
View remediation
65535 )); then printf 'Invalid SSH port: %s\n' "$SSH_PORT" >&2 exit 1 fi ``` 3. Replace string-based execution with an array-aware helper: ```bash run() { if [[ "$DRY_RUN" == "true" ]]; then printf '[DRY-RUN]' printf ' %q' "$@" printf '\n' else "$@" fi } run ufw allow "${SSH_PORT}/tcp" comment SSH ``` 4. Generate configuration files using safe templates after validation. Do not pass heredoc construction through `eval`. 5. Validate all other user-controlled options, including `OPENCLAW_USER` and `OPENCLAW_CONFIG_DIR`, according to strict expected formats. 6. Add regression tests using shell metacharacters, whitespace, command substitutions, negative numbers, and out-of-range ports. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/harden.sh:84
Finding

Unsafe Firewall and SSH Reconfiguration Can Cause Administrative Lockout

Content
View full analysis
Remediation
View remediation

other

Warning
Location
scripts/harden.sh:6
Finding

Declared Non-Root OpenClaw Isolation Is Not Implemented

Content
View full analysis
Remediation
View remediation
/dev/null 2>&1; then useradd --system --create-home --shell /usr/sbin/nologin "$OPENCLAW_USER" fi ``` 2. Validate `OPENCLAW_USER` against an appropriate username pattern before using it. 3. Move the OpenClaw configuration to an appropriate service-owned directory or carefully assign ownership only to files the service must access. 4. Add a systemd override containing at least: ```ini [Service] User=koda Group=koda NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=true ``` Required writable paths should be explicitly granted with `ReadWritePaths=`. 5. Reload systemd, restart OpenClaw, and verify the effective process identity: ```bash systemctl daemon-reload systemctl restart openclaw systemctl show openclaw -p User -p Group ps -o user,group,pid,cmd -C openclaw ``` 6. If non-root migration cannot be implemented safely, remove the option and all claims that the control has been applied. Report the actual service UID in the completion summary. ]]>
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
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (22)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 97)May include surrounding context.

md
### Layer 6 — File Permissions
- `~/.openclaw/` → mode 700
- `openclaw.json`, `secrets.json` → mode 600
- `~/.cloudflared/` → mode 700, credentials → mode 600
- SSH authorized_keys → mode 600

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/harden.sh (reported line 254)May include surrounding context.

sh
### Layer 6 — File Permissions
- `~/.openclaw/` → mode 700
- `openclaw.json`, `secrets.json` → mode 600
- `~/.cloudflared/` → mode 700, credentials → mode 600
- SSH authorized_keys → mode 600

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Using ufw --force reset is dangerous because it destroys the existing firewall policy before applying new rules, which can remove previously required protections or momentarily alter access in unexpected ways. In a public VPS hardening context, this is more risky than usual because operators may have custom deny/allow rules, rate limits, or management ports that are silently wiped, potentially causing exposure or lockout.

Content

Scanner excerpt · scripts/harden.sh (reported line 94)May include surrounding context.

sh
run "apt-get install -y ufw -qq"

  # Reset to clean state
  run "ufw --force reset"

  # Defaults
  run "ufw default deny incoming"

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/harden.sh (reported line 135)May include surrounding context.

sh
apply_ssh "PermitRootLogin"         "no"
  apply_ssh "PasswordAuthentication"  "no"
  apply_ssh "PubkeyAuthentication"    "yes"
  apply_ssh "AuthorizedKeysFile"      ".ssh/authorized_keys"
  apply_ssh "PermitEmptyPasswords"    "no"
  apply_ssh "X11Forwarding"           "no"
  apply_ssh "MaxAuthTries"            "3"

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/harden.sh (reported line 150)May include surrounding context.

sh
fi

  ok "SSH: port ${SSH_PORT}, root login disabled, password auth disabled"
  warn "IMPORTANT: Ensure your SSH key is in ~/.ssh/authorized_keys BEFORE reconnecting"
  warn "Test connection: ssh -p ${SSH_PORT} root@SERVER_IP (in a NEW terminal, don't close this one)"
fi

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/harden.sh (reported line 268)May include surrounding context.

sh
# SSH keys
run "chmod 700 /root/.ssh 2>/dev/null || true"
run "chmod 600 /root/.ssh/authorized_keys 2>/dev/null || true"
ok "SSH keys: mode 700/600"

# ─── Summary ──────────────────────────────────────────────────────────────────

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill instructs users to copy and execute a hardening shell script over SSH, which clearly implies shell and file-write capabilities, but the skill metadata does not declare any tool scope such as allowed-tools or permissions. In an agent ecosystem, undeclared execution capability weakens policy enforcement and increases the chance that a consumer runs a skill with broader authority than expected, especially because the actions modify firewall and SSH settings on a live VPS.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The document recommends Cloudflare Access service tokens as the 'best approach' for a native phone app even though those tokens are effectively long-lived shared secrets, not end-user identity assertions. In a mobile app context, secrets embedded in the client can often be extracted through reverse engineering, device compromise, logging, or proxying; once recovered, the token can bypass the intended per-user identity gate and grant persistent agent access until manually rotated or revoked.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The guidance omits an explicit warning that a Cloudflare service token's client ID and especially client secret should not be embedded in a distributable native phone app. Without that warning, implementers may hardcode the secret into mobile binaries or app configs, creating a recoverable credential that enables unauthorized access to the protected OpenClaw agent and undermines the document's defense-in-depth and identity-gating goals.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The header comments describe 'Layer 6: Non-root user for OpenClaw service' as part of the implemented hardening strategy. However, the script contains no useradd/usermod/systemd service reconfiguration logic, and the actual Layer 6 implemented later is file permission hardening instead. This is an active contradiction between the documented intent and the code's behavior.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/harden.sh (reported line 20)May include surrounding context.

sh
# Usage:
#   bash harden.sh [--ssh-port 2222] [--openclaw-user koda] [--skip-ufw] [--dry-run]
#
# Run as root on the VPS.

set -euo pipefail

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/harden.sh (reported line 74)May include surrounding context.

sh
# Usage:
#   bash harden.sh [--ssh-port 2222] [--openclaw-user koda] [--skip-ufw] [--dry-run]
#
# Run as root on the VPS.

set -euo pipefail

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/harden.sh (reported line 186)May include surrounding context.

sh
bantime  = 3600
EOF"

  run "systemctl enable fail2ban"
  run "systemctl restart fail2ban"

  if [[ "$DRY_RUN" != "true" ]]; then

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/harden.sh (reported line 252)May include surrounding context.

sh
# Secure OpenClaw config dir
if [[ -d "$OPENCLAW_CONFIG_DIR" ]]; then
  run "chmod 700 ${OPENCLAW_CONFIG_DIR}"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/openclaw.json 2>/dev/null || true"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/secrets.json 2>/dev/null || true"
  ok "OpenClaw config: mode 700/600"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/harden.sh (reported line 260)May include surrounding context.

sh
# Secure OpenClaw config dir
if [[ -d "$OPENCLAW_CONFIG_DIR" ]]; then
  run "chmod 700 ${OPENCLAW_CONFIG_DIR}"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/openclaw.json 2>/dev/null || true"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/secrets.json 2>/dev/null || true"
  ok "OpenClaw config: mode 700/600"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/harden.sh (reported line 267)May include surrounding context.

sh
# Secure OpenClaw config dir
if [[ -d "$OPENCLAW_CONFIG_DIR" ]]; then
  run "chmod 700 ${OPENCLAW_CONFIG_DIR}"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/openclaw.json 2>/dev/null || true"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/secrets.json 2>/dev/null || true"
  ok "OpenClaw config: mode 700/600"

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/harden.sh (reported line 253)May include surrounding context.

sh
# Secure OpenClaw config dir
if [[ -d "$OPENCLAW_CONFIG_DIR" ]]; then
  run "chmod 700 ${OPENCLAW_CONFIG_DIR}"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/openclaw.json 2>/dev/null || true"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/secrets.json 2>/dev/null || true"
  ok "OpenClaw config: mode 700/600"
fi

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/harden.sh (reported line 254)May include surrounding context.

sh
# Secure OpenClaw config dir
if [[ -d "$OPENCLAW_CONFIG_DIR" ]]; then
  run "chmod 700 ${OPENCLAW_CONFIG_DIR}"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/openclaw.json 2>/dev/null || true"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/secrets.json 2>/dev/null || true"
  ok "OpenClaw config: mode 700/600"
fi

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/harden.sh (reported line 261)May include surrounding context.

sh
# Secure OpenClaw config dir
if [[ -d "$OPENCLAW_CONFIG_DIR" ]]; then
  run "chmod 700 ${OPENCLAW_CONFIG_DIR}"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/openclaw.json 2>/dev/null || true"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/secrets.json 2>/dev/null || true"
  ok "OpenClaw config: mode 700/600"
fi

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/harden.sh (reported line 262)May include surrounding context.

sh
# Secure OpenClaw config dir
if [[ -d "$OPENCLAW_CONFIG_DIR" ]]; then
  run "chmod 700 ${OPENCLAW_CONFIG_DIR}"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/openclaw.json 2>/dev/null || true"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/secrets.json 2>/dev/null || true"
  ok "OpenClaw config: mode 700/600"
fi

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/harden.sh (reported line 268)May include surrounding context.

sh
# Secure OpenClaw config dir
if [[ -d "$OPENCLAW_CONFIG_DIR" ]]; then
  run "chmod 700 ${OPENCLAW_CONFIG_DIR}"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/openclaw.json 2>/dev/null || true"
  run "chmod 600 ${OPENCLAW_CONFIG_DIR}/secrets.json 2>/dev/null || true"
  ok "OpenClaw config: mode 700/600"
fi

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The summary line says 'SSH — no root' and the script sets PermitRootLogin no, but the final instructions immediately tell the operator to reconnect using 'ssh -p ${SSH_PORT} root@YOUR_SERVER_IP'. That guidance contradicts the configured SSH policy and can mislead users about what access method the script leaves available.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.