Back to skill

Security audit

OpenClaw Documentation Expert — Live Fetch

Security checks for vulnerabilities and agentic risk

Overview

This OpenClaw docs helper is mostly purpose-aligned, but it should be reviewed because it can persist full user questions locally and documents unsafe shell use with user input.

Review before installing. The skill appears intended for OpenClaw documentation lookup and does not show destructive behavior or unrelated exfiltration, but users should avoid asking it questions containing secrets and should prefer a patched version that disables raw miss logging, redacts stored questions, uses structured argument passing, and stores caches/logs with private permissions.

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
SKILL.md:32
Finding

Shell Command Injection Through Interpolated User Question

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:32
Vulnerability Type: Command injection caused by unsafe shell-command construction
Risk Level: High

Vulnerable Code

text
7. If you had to fall back to `find.sh` or `search.sh`, or if the user corrects your routing, log the miss: `scripts/record_miss.sh "<user question>" "<path you used>"`

The corresponding script expects the question as a command-line argument:

bash
# Record mode:
#   record_miss.sh "<user question>" "<path you ended up fetching>"

Technical Analysis

The Skill instructs the agent to insert an attacker-controlled user question directly into a textual shell command surrounded by double quotes. Double quotes do not safely encode arbitrary data for a shell: an embedded double quote can terminate the argument, after which shell metacharacters, command substitutions, or additional commands can be interpreted.

The implementation of record_miss.sh treats already-separated arguments as data, but this protection occurs only after shell parsing. It does not protect the command-construction step prescribed by SKILL.md.

Exploitability depends on the host agent executing the documented command through a shell rather than passing a structured argument vector. Under that execution model, a crafted question such as a quote followed by a command separator could introduce an additional command.

Attack Path

  1. An attacker submits an OpenClaw-related question containing shell syntax and an embedded double quote.
  2. The question causes routing to fall back to find.sh or search.sh, or the attacker corrects the routing.
  3. The Behavior Contract requires the agent to run the documented miss-logging command.
  4. The agent substitutes the raw question into the quoted shell command.
  5. Shell parsing terminates the intended argument at the attacker-supplied quote.
  6. The remaining attacker-controlled ...[truncated 583 chars]
Remediation
View remediation

Remediation Suggestions

  • Do not construct shell command strings by interpolating user-controlled questions.
  • Invoke record_miss.sh through an API that accepts a structured argument array, without an intervening shell.
  • Prefer accepting the question through standard input, for example by adding a mode in which record_miss.sh reads one bounded record from stdin.
  • If shell invocation is unavoidable, apply a trusted shell-escaping routine to each argument rather than relying on double quotes.
  • Add tests containing embedded quotes, backticks, command substitutions, semicolons, newline characters, and shell redirection operators.
  • Consider removing the raw question from the logging interface entirely and recording only a sanitized routing keyword or event identifier.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/record_miss.sh:44
Finding

Persistent Storage of Unredacted User Questions

Content
View full analysis

Vulnerability Details

File Location: scripts/record_miss.sh:44-52
Vulnerability Type: Plaintext retention of potentially sensitive conversation data
Risk Level: Medium

Vulnerable Code

bash
q="$1"
path="$2"
mkdir -p "$dir"
if [ ! -f "$log" ]; then
  printf '# Routing misses\n\nOne line per miss: timestamp | question | fetched path.\nPromote to SKILL.md Synonym Map only after 3 comparable hits.\nRun `record_miss.sh --tally` to see counts.\n\n' > "$log"
fi
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
# Flatten newlines in the question so each miss stays on one line.
q_one=$(printf '%s' "$q" | tr '\n' ' ')
printf '%s | %s | %s\n' "$ts" "$q_one" "$path" >> "$log"
printf 'recorded: %s\n' "$log"

Technical Analysis

When routing falls back or is corrected, the script persistently appends the complete user question to:

text
~/.openclaw/openclaw-docs/misses.md

User questions may contain API keys, access tokens, private hostnames, internal configuration, personal information, or excerpts from confidential files. The only transformation is replacement of newline characters with spaces. There is no secret redaction, data classification, user consent, retention period, size limit, or automatic deletion.

The script also relies on the process umask when creating the directory and log file rather than explicitly enforcing restrictive permissions. Consequently, confidentiality depends on host configuration.

This storage supports route-maintenance analytics, but retaining the complete question is not required for the Skill’s primary documentation-fetching function and exceeds the minimum data retention needed.

Attack Path

  1. A user asks a question containing sensitive information.
  2. The query triggers find.sh or search.sh, or the user corrects the selected route.
  3. The Skill invokes record_miss.sh with the complete question.
  4. The script writes the flattened quest ...[truncated 668 chars]
Remediation
View remediation

Remediation Suggestions

  • Record only the minimum information needed, such as a normalized topic, sanitized keyword, route identifier, and miss count.
  • Do not retain the full user question by default; require explicit user or administrator opt-in if full-text logging is necessary.
  • Redact common credential formats, authorization headers, private keys, tokens, passwords, and sensitive configuration values before writing.
  • Create the directory with mode 0700 and the log with mode 0600, independently of the caller’s umask.
  • Add configurable retention and automatic deletion or aggregation after a short period.
  • Document the storage location, purpose, retention period, and deletion procedure.
  • Bound the maximum accepted record length to prevent uncontrolled log growth.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/search.sh:13
Finding

Predictable Shared Temporary Cache Allows Symlink-Based File Overwrite

Content
View full analysis

Vulnerability Details

File Location: scripts/search.sh:13-26
Vulnerability Type: Unsafe predictable temporary file
Risk Level: Medium

Vulnerable Code

bash
kw="$1"
ctx="${2:-10}"
cache="${TMPDIR:-/tmp}/openclaw-llms-full.txt"
max_age=3600  # seconds

# Refresh cache if missing or older than max_age.
needs_fetch=1
if [ -f "$cache" ]; then
  if mtime=$(stat -f %m "$cache" 2>/dev/null || stat -c %Y "$cache" 2>/dev/null); then
    age=$(( $(date +%s) - mtime ))
    [ "$age" -lt "$max_age" ] && needs_fetch=0
  fi
fi
if [ "$needs_fetch" -eq 1 ]; then
  curl -sfL https://docs.openclaw.ai/llms-full.txt > "$cache.tmp"
  mv "$cache.tmp" "$cache"
fi

Technical Analysis

Both the cache path and staging path are predictable:

text
/tmp/openclaw-llms-full.txt
/tmp/openclaw-llms-full.txt.tmp

In a shared temporary directory, another local user can create the .tmp path before the victim runs the script. Shell output redirection follows symbolic links on systems where platform-level symlink protections do not block the operation. If the predictable path is a symlink to a file writable by the victim, the redirection truncates and replaces that target with downloaded documentation.

The shared cache name also permits cross-user interference with search results. Exploitability can be reduced by operating-system protections such as protected symlinks, but the script is intended for portable POSIX-like environments and does not enforce a private cache location itself.

Attack Path

  1. A local attacker predicts the fixed staging filename in the shared temporary directory.
  2. The attacker creates /tmp/openclaw-llms-full.txt.tmp as a symbolic link to a file the victim can write.
  3. The victim runs search.sh while the cache is missing or stale.
  4. Shell redirection opens the attacker-created path before curl starts.
  5. If symbolic-link traversal is ...[truncated 695 chars]
Remediation
View remediation

Remediation Suggestions

  • Create a private, per-user cache directory with mode 0700; prefer an established user cache directory over a shared /tmp namespace.
  • Generate the staging file with mktemp inside that private directory.
  • Install a trap that removes the unique staging file on exit.
  • Download into the unique file and atomically rename it to the final cache path only after a successful transfer.
  • Verify that the final cache path is a regular file owned by the current user and reject symbolic links.
  • Create cache files with mode 0600.
  • Consider validating the downloaded response’s size and expected format before replacing the active cache.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Rogue AgentSelf-Modification, Session Persistence
Findings (18)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description describes a much broader documentation retrieval and validation capability than the supplied code actually implements. The code only defines a helper script to fetch a single page from docs.openclaw.ai based on a provided path. It does not index the full docs set, perform self-tests, provide routing examples, or demonstrate coverage of the listed domains. The resource accessed is consistent with the description (docs.openclaw.ai), but the primary purpose and scope are materially narrower than declared.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description describes a broad documentation-retrieval and validation capability, including live per-question fetching, whole-doc indexing, self-tests, examples, and topic coverage. The supplied code only implements a narrow helper script: it downloads one index-like text file from docs.openclaw.ai and filters entries by a keyword in title or path. While this partially relates to documentation lookup, it falls far short of the declared scope and omits most of the advertised functionality. There are no extra risky or unrelated capabilities, but the primary purpose and breadth are materially overstated by the description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents a documentation-fetching and indexing skill with self-test and broad doc coverage. The supplied code does none of that. It is a standalone local logging utility for recording and summarizing routing misses, writing to a file in the user's home directory. This is a materially different primary purpose and includes an undeclared capability (local persistence/logging) while lacking the core declared behaviors (live docs fetching, indexing, self-testing, and coverage features).

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The code’s primary behavior is a cached full-text search helper for a single downloaded documentation text file. The description overstates functionality in several material ways: it explicitly says it fetches live on every question, but the script intentionally avoids re-downloading for up to an hour; it mentions working scripts, CI-style self-tests, and worked routing examples, none of which are present in this code chunk; and it claims broad topical coverage that is not implemented as logic, only potentially present in the remote text content. The core theme of searching OpenClaw docs is related, but the declared description is not an accurate representation of this specific code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The supplied code chunk matches one narrow part of the description: a CI-style self-test to detect stale or missing referenced docs and a smoke test for fetch.sh. However, the declared purpose prominently claims broader runtime behavior and coverage, including live fetching from docs.openclaw.ai on every question, a whole-docs index, working scripts generally, and topic/example coverage. None of those broader capabilities are present in this code chunk. The code’s primary behavior is validation of referenced documentation paths, not live question-time documentation retrieval or indexing. Therefore the description overstates what this specific code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code does access docs.openclaw.ai live and serves as a basic verification script, so part of the description is supported. However, the description promises substantially broader functionality: live fetching on every question, a whole-docs index, working scripts plural, CI-style self-testing for decision-tree degradation, routing examples, and broad content coverage across several OpenClaw domains. This code chunk only verifies retrieval of a single llms.txt document and reports metadata about that fetch. The primary behavior is narrower than the declared purpose, so the description materially overstates what the code actually does.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- **`selftest.sh`** — HEAD-check every doc path referenced in SKILL.md and EXAMPLES.md, in parallel (8 workers; override with `PARALLEL=N`). Classifies STALE (3

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- **`selftest.sh`** — HEAD-check every doc path referenced in SKILL.md and EXAMPLES.md, in parallel (8 workers; override with `PARALLEL=N`). Classifies STALE (3

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- **`selftest.sh`** — HEAD-check every doc path referenced in SKILL.md and EXAMPLES.md, in parallel (8 workers; override with `PARALLEL=N`). Classifies STALE (3

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- **`selftest.sh`** — HEAD-check every doc path referenced in SKILL.md and EXAMPLES.md, in parallel (8 workers; override with `PARALLEL=N`). Classifies STALE (3

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- Do not edit `SKILL.md`, `EXAMPLES.md`, or any file under `scripts/` from within an agent answer.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares shell capability requirements (curl and script execution behavior) but does not define any explicit tool scope such as allowed commands, paths, or permission boundaries. That creates unnecessary execution ambiguity: a host agent may grant broader shell access than needed, increasing the blast radius if the skill is abused or if downstream prompts induce unexpected command execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill instructs the agent to log the user's question to a persistent local file when routing fails or is corrected, but it does not require notice, consent, minimization, or redaction. This can retain sensitive prompts, credentials, internal URLs, or personal data in plaintext on disk, creating a privacy and forensic exposure risk beyond the immediate conversation.

Content

No source excerpt is available for this finding.

Persistent Context Injection

Medium
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill injects content designed to persist in agent memory or context across interactions. Persistent injection can alter agent behavior long after the initial interaction.

Content

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

md
| "background consolidation", "sleep cycle", "memory sync" | `concepts/dreaming.md` |
| "scheduled task", "recurring job", "crontab" | `automation/cron-jobs.md` |
| "pre/post-tool hook", "lifecycle event" | `automation/hooks.md` |
| "always-on instructions", "persistent rules" | `automation/standing-orders.md` |
| "bot", "messenger", "chat integration" | CHANNELS → `channels/<name>.md` |
| "jail", "isolation", "sandbox" | `gateway/sandboxing.md` |
| "firewall", "egress rules", "allowlist" | `gateway/network-model.md` |

Session Persistence

Medium
Category
Rogue Agent
Confidence
95% confidence
Finding

The skill explicitly permits writing user-derived content to a persistent file under ~/.openclaw/openclaw-docs/ via record_miss.sh. Even though it says not to exfiltrate beyond the flattened question, this still creates durable storage of potentially sensitive user input and may expose it to other local users, backups, logs, or later tooling that reads the file.

Content

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

md
- Do not edit `SKILL.md`, `EXAMPLES.md`, or any file under `scripts/` from within an agent answer.
- Do not invent new decision-tree branches on the fly — use the current tree, then log the miss.
- Do not write to `~/.openclaw/openclaw-docs/` anything other than the misses log (one append per miss).
- Do not exfiltrate user messages beyond the single flattened question passed to `record_miss.sh`.

Promotions from the misses log into SKILL.md are a **human commit**, reviewed, run through `selftest.sh`, and published as a new version. The agent proposes; the maintainer disposes.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script persistently logs the full user question to a local file under the user's home directory, which can capture secrets, internal URLs, credentials, API tokens, or other sensitive prompts unrelated to the narrow purpose of routing analytics. Because the logging is automatic, unredacted, and retained across runs, it creates a data exposure risk if the filesystem is shared, backed up, synced, or later inspected by other tools or users.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/verify.sh (reported line 10)May include surrounding context.

sh
tmp=$(mktemp)
hdr=$(mktemp)
trap 'rm -f "$tmp" "$hdr"' EXIT
curl -sfL -D "$hdr" "$url" > "$tmp"
pages=$(grep -c "^- \[" "$tmp" || true)
if command -v shasum >/dev/null 2>&1; then
  sha=$(shasum -a 256 "$tmp" | awk '{print $1}')

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The manifest centers the skill on live documentation retrieval and coverage of documentation topics. This file instead implements a local miss recorder and tally tool that appends user questions to ~/.openclaw/openclaw-docs/misses.md and summarizes them, which is ancillary behavior not reflected in the manifest description.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.