T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/embed.py:80- Finding
Arbitrary Local File Disclosure Through Remote Embedding and Indexing
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a mostly coherent local wiki skill, but it needs review because some helper workflows can reach outside the intended local wiki boundary and send private content to external services.
Install only if you are comfortable with a persistent local wiki that may store client/account/history data in markdown logs and caches. Keep WIKI_ROOT private, use a scoped filesystem MCP server, avoid shell fallback for untrusted input, do not ingest untrusted URLs without network controls, and skip embed.py unless you explicitly want wiki content sent to AWS Bedrock and OpenSearch under a constrained account and index.
scripts/embed.py:80Arbitrary Local File Disclosure Through Remote Embedding and Indexing
scripts/dedup.py:62Server-Side Request Forgery and Unbounded Download in URL Deduplication
scripts/ingest.md:18Shell Command Injection Through Unescaped Skill Placeholders
README.md:170Unpinned Package Download and Execution Through npx
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).
$WIKI_ROOT/.lint-history/YYYY-MM-DD.md # 持久化报告
stdout # 完整报告或一行摘要(带 --summary)
推送通知?自行在 cron/Task Scheduler 里 pipe:
python3 lint.py --summary | mail -s 'wiki lint' you@example.com
python3 lint.py --summary | xargs -I{} openclaw message send --target user:xxx --message {}
python3 lint.py --summary | curl -X POST -d @- https://hooks.slack.com/services/...
"""
import os
import re
import sys
import argparse
from datetime import datetime, timedelta
from pathlib import Path
from collections import defaultdict
def default_wiki_root() -> Path:
env = os.environ.get("WIKI_ROOT")
if env:
return Path(env).expanduser()
return Path.home() / ".openclaw/workspace/wiki"
# "缺失交叉引用"判定:两个页面如果标题/标签相似度高,但互相没 [[链接]],可能漏了交叉引用
# 简化版:同目录下的页面,如果页面 A 的正文提到页面 B 的标�
The documented purpose presents a local wiki skill, but the behavior includes arbitrary HTTP/HTTPS fetches and omits several promised behaviors. This mismatch is dangerous because users and orchestrators may trust the skill under a narrower local-only threat model, while the actual workflow can exfiltrate prompts or ingest attacker-controlled remote content, expanding the attack surface significantly.
The README states that every ingest, query, and lint operation is append-only logged in natural language. In a persistent local wiki handling potentially sensitive user knowledge, this can retain prompts, source references, and derived answers longer than expected, increasing disclosure risk if the wiki directory is accessed, synced, backed up, or committed accidentally.
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.
Only the *shell one-liners* in this README differ per OS — see platform-specific blocks below.
> **Heads-up**: this skill relies on an **Obsidian filesystem MCP server** as its primary
> read/write channel. It falls back to `read`/`write`/`edit` tools if MCP isn't wired up, but
> you get meaningfully better behavior (sandboxing, structured errors) with it. See
> [Dependencies](#-dependencies) below.
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.
### Strongly recommended: Obsidian filesystem MCP server
This skill is **designed around an Obsidian-style filesystem MCP server** as its primary
read/write channel. All operating rules in [`SKILL.md`](./SKILL.md) assume the LLM can call
`obsidian.read_text_file`, `obsidian.write_file`, `obsidian.edit_file`, `obsidian.list_directory`,
`obsidian.search_files`, and `obsidian.list_allowed_directories`.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
# Slack incoming webhook
python3 .../lint.py --summary | \
xargs -I{} curl -s -X POST -H 'Content-type: application/json' \
--data '{"text":"{}"}' https://hooks.slack.com/services/XXX/YYY/ZZZ
# Any chat via openclaw CLI (Feishu / Discord / Telegram / Slack / ...)
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
# Slack incoming webhook
python3 .../lint.py --summary | \
xargs -I{} curl -s -X POST -H 'Content-type: application/json' \
--data '{"text":"{}"}' https://hooks.slack.com/services/XXX/YYY/ZZZ
# Any chat via openclaw CLI (Feishu / Discord / Telegram / Slack / ...)
The skill instructs the agent to use environment variables, local file reads/writes, shell commands, and MCP-based operations, but it declares no explicit tool scope or permission boundaries. That creates a real least-privilege gap: if the runtime exposes broader tools than intended, the skill can read, modify, or fetch beyond the wiki workflow without any machine-readable restriction.
The skill claims it should activate for technical questions that 'should check long-lived local knowledge first,' which is subjective and broad. Over-broad triggers can cause the agent to access local persistent knowledge, including sensitive historical/client data, when the user did not explicitly request wiki use, creating confidentiality and consent risks.
The trigger table activates based on sensitive-topic categories like customers, historical decisions, or account information rather than an explicit instruction to consult the wiki. In this context, that increases the chance of unprompted retrieval or persistence of sensitive local information, especially because the wiki is a long-lived store and the skill may later write updates and logs.
The ingest flow states that one operation may create or modify 5-15 pages, update the index, append to logs, and record dedup metadata, but the skill description does not clearly warn users about this breadth of local state change. That is a real safety issue because users may issue a seemingly simple ingest request without understanding the persistence, fan-out, and audit trail implications for local sensitive content.
The script writes a JSON cache containing the source path/URL, title, wiki page path, timestamp, and size to disk. Although the cache location is documented, there is no explicit warning that running the record command will persist potentially sensitive source metadata locally, which is relevant user disclosure for file-writing behavior.
The script will fetch arbitrary http/https URLs supplied as input, which can cause unintended outbound connections and disclosure of network metadata such as IP, DNS, and access timing. In a local knowledge-ingest tool, this also creates SSRF-style risk if untrusted users can influence the URL, potentially reaching internal services or sensitive endpoints.
The script retrieves OpenSearch connection details from AWS Secrets Manager, granting it access to cloud secrets unrelated to a narrowly described local wiki function. While using a secret manager is standard practice, the undisclosed secret access expands privilege and makes compromise or misuse of the skill more damaging.
The script sends data to AWS Bedrock for embedding generation and writes to a remote OpenSearch cluster, which contradicts the skill description of a long-lived local wiki. In this context, user-supplied or locally stored wiki content may be exfiltrated to external services without clear consent, making the trust boundary much broader than advertised.
Indexing stores the full page content remotely in OpenSearch, not just embeddings or metadata. That means sensitive notes, credentials, customer data, or internal documentation placed in the wiki could be replicated into a remote service, increasing exposure and violating user expectations of a persistent local knowledge base.
The indexing flow transmits page-derived data to external AWS services with only minimal progress output and no meaningful warning, consent prompt, or privacy notice. In a wiki skill that appears local/persistent, this omission can cause users to unknowingly upload sensitive material outside their machine or trusted environment.
The ingest workflow is triggered for broad conditions such as when a user provides a document, URL, or when the agent produces a 'valuable answer'. In a skill that performs persistent wiki writes, this can cause unintended invocation and storage of content without sufficiently explicit user intent, increasing the chance of accidental data retention or pollution of long-lived knowledge.
The document defines multiple write and edit operations against persistent wiki files, including creating pages, editing existing pages, updating logs, and modifying the index, but it does not require a user-facing warning or confirmation before these changes occur. In a persistent knowledge skill, silent modification is risky because it can unexpectedly alter stored data, create inaccurate records, or persist sensitive user content without clear awareness.
Using the bare trigger phrase "lint" for Layer 2 activation is overly broad and can cause the agent to enter a read/write wiki maintenance workflow when the user meant something else, such as discussing linting generally or referring to another tool. In this skill, unintended activation is more dangerous because Layer 2 includes file reads, possible file writes via Obsidian MCP, and even fallback execution of a local Python script, so a misfire can lead to unnecessary access or modification of persistent local knowledge.
The docstring states the script behavior and the Layer 2 trigger entirely in Chinese, including the explicit trigger phrase "整理 wiki". This imposes a specific language for invocation and usage without any opt-in or alternative locale, which matches the language/locale policy-violation criterion.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
推送通知?自行在 cron/Task Scheduler 里 pipe:
python3 lint.py --summary | mail -s 'wiki lint' you@example.com
python3 lint.py --summary | xargs -I{} openclaw message send --target user:xxx --message {}
python3 lint.py --summary | curl -X POST -d @- https://hooks.slack.com/services/...
"""
import os
The generated report tells the user to say "整理 wiki" to trigger Layer 2 processing, with no alternative language or opt-in. Because this is user-facing natural-language output embedded in code, it enforces a single locale and can violate organizational language-choice policy.
The activation rule covers general 'technical questions' and says to use the skill after answering valuable technical questions, making invocation broad enough to trigger on many ordinary prompts. Over-broad activation is risky because it can cause unexpected file access, tool use, or external lookups in contexts where the user did not intend the wiki workflow to run.
The skill explicitly instructs the agent to query whatever external MCP servers are configured by the user and to fall back to web search, which expands behavior beyond local wiki retrieval into arbitrary outbound data access. This creates a real data exposure and scope-expansion risk because user queries may be sent to third-party services without strong allowlisting, capability restriction, or per-request consent.
No suspicious patterns detected.