Back to skill

Security audit

OpenClaw Docs

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent OpenClaw documentation helper, but its scripts accept overly broad URL and file inputs that can reach non-doc services, write outside the intended cache, or print local file contents.

Review before installing. Use this only in an environment where shell scripts cannot be driven by untrusted input, avoid passing full URLs or local file paths to its commands, and prefer a fixed docs.openclaw.ai-only version that validates cache paths before writing.

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/lib.sh:61
Finding

Unrestricted documentation URL enables server-side request forgery

Content
View full analysis
&2 return 1 fi if [[ "$input" =~ ^https?:// ]]; then local base_no_query query base_no_query="${input%%\?*}" query="" if [[ "$input" == *\?* ]]; then query="?${input#*\?}" fi if [[ "$base_no_query" != *.md ]]; then base_no_query="${base_no_query%/}.md" fi printf '%s%s\n' "$base_no_query" "$query" return fi local path="$input" path="${path#/}" path="${path%.html}" if [[ "$path" != *.md ]]; then path="${path}.md" fi printf '%s/%s\n' "$BASE_URL" "$path" } download_doc() { local url="$1" local dest tmp force_fetch ensure_cache_dirs dest=$(doc_cache_path "$url") mkdir -p "$(dirname "$dest")" force_fetch="${OPENCLAW_DOCS_FORCE_FETCH:-0}" if [[ -s "$dest" && "$force_fetch" != "1" ]]; then printf '%s\n' "$dest" return fi tmp="${dest}.tmp" curl -fsSL "$url" -o "$tmp" mv "$tmp" "$dest" printf '%s\n' "$dest" } ``` The vulnerable functionality is directly exposed by `fetch-doc.sh`: ```bash url=$(normalize_doc_url "$1") cache_path=$(download_doc "$url") echo "# Source: $url" echo "# Cached: $cache_path" echo cat "$cache_path" ``` ### Technical Analysis `normalize_doc_url` accepts every string beginning with `http://` or `https://`. It does not require the exact documented host, `docs.openclaw.ai`, and does not reject loopback, link-local, private-network, or other non-documentation destinations. The resulting URL is passed directly to `curl`. The `-L` option also permits redirects, but the final redirect destination is not validated. Consequently, vali ...[truncated 1674 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/lib.sh:91
Finding

Untrusted URL path permits writes outside the documentation cache

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lib.sh:134
Finding

Snapshot resolver accepts arbitrary local files and may disclose their contents

Content
View full analysis
"$a" sort "$newer" > "$b" added=$(mktemp) removed=$(mktemp) comm -13 "$a" "$b" > "$added" comm -23 "$a" "$b" > "$removed" echo "Comparing $(basename "$older") -> $(basename "$newer")" echo echo "Added pages: $(wc -l < "$added" | tr -d ' ')" if [[ -s "$added" ]]; then cut -f1,2 "$added" else echo "(none)" fi echo echo "Removed pages: $(wc -l < "$removed" | tr -d ' ')" if [[ -s "$removed" ]]; then cut -f1,2 "$removed" else echo "(none)" fi } ``` The arbitrary path is reachable through the `since` command: ```bash ref="${2:-}" older="" if older=$(resolve_snapshot "$ref" 2>/dev/null); then : else cutoff=$(date -u -d "$ref" +%s 2>/dev/null || true) if [[ -n "$cutoff" ]]; then older=$(find "$CACHE_DIR/snapshots" -maxdepth 1 -type f -name '*.tsv' -printf '%T@ %p\n' | sort -n | awk -v t="$cutoff" '$1 >= t {print substr($0, index($0,$2)); exit}') fi fi ... compare_snapshots "$older" "$latest" ``` ### Technical Analysis The documented input is a snapshot prefix or date, but `resolve_snapshot` first accepts any existing regular file: ```bash if [[ -f "$r ...[truncated 1700 chars]
Remediation
View remediation
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (1)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill instructs the agent to execute multiple shell scripts, but it does not declare any explicit tool scope such as allowed tools or permissions. This creates an authorization ambiguity where a consumer may permit shell execution more broadly than intended, increasing the chance of unintended command execution against the local environment or network.

Content

No source excerpt is available for this finding.