Back to skill

Security audit

Wikisage

Security checks for vulnerabilities and agentic risk

Overview

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.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/embed.py:80
Finding

Arbitrary Local File Disclosure Through Remote Embedding and Indexing

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/dedup.py:62
Finding

Server-Side Request Forgery and Unbounded Download in URL Deduplication

Content
View full analysis
``` 3. The URL points directly to an internal service or redirects to one. 4. The deduplication script performs the request from the agent's network context. 5. The script reads the complete response into memory to calculate its SHA-256 hash. 6. Depending on the target and response, the result may: - Reach otherwise inaccessible internal services. - Trigger state-changing actions ...[truncated 940 chars]
Remediation
View remediation
limit: raise ValueError("Response exceeds the permitted size") digest.update(chunk) ``` 8. Validate the response content type and reject unexpected binary or executable content where appropriate. 9. Apply outbound network controls so the process cannot access metadata services or sensitive internal networks. 10. Log blocked destinations without recording credentials or sensitive URL query parameters. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/ingest.md:18
Finding

Shell Command Injection Through Unescaped Skill Placeholders

Content
View full analysis
``` ```bash python3 $WIKI_SKILL_DIR/scripts/dedup.py \ record pages//.md "Source title" ``` The query workflow also directs the agent to interpolate a search term into a shell command: ```bash exec grep -rn "keyword" $WIKI_ROOT/pages/ ``` ### Technical Analysis The Skill documentation instructs an agent to construct shell commands using dynamic values such as: - Source file paths - Source URLs - Wiki categories and slugs - Source titles - Search terms - Environment-controlled directory paths The ingest source placeholder is unquoted. If an agent performs direct textual substitution, shell metacharacters in a URL or filename can be interpreted as command syntax. The grep example places a dynamic search term inside double quotes, but double quoting alone is not safe when the interpolated value can contain quote characters, command substitutions, backticks, or other shell syntax. Environment-derived paths are also unquoted. These Markdown files define operational behavior for a tool-using agent. Therefore, unsafe command templates can become executable vulnerabilities even though they are not Python code. ### Attack Path 1. An attacker provides a crafted ingest source or wiki search term. 2. The value contains shell syntax, such as a command separator or command substitution. 3. The agent follows the documented workflow and substitutes the value into the shell command. 4. A shell parses the resulting command instead of passing the value as one inert argument. 5. The injected command executes with the same privileges and filesystem or network access as the agent process. For example, an unsafe textual substitution o ...[truncated 901 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
README.md:170
Finding

Unpinned Package Download and Execution Through npx

Content
View full analysis
"] } } } ``` ### Technical Analysis The recommended MCP configuration uses `npx -y` to obtain and execute `@modelcontextprotocol/server-filesystem` without an exact package version or integrity constraint. As a result, the effective executable can change after this Skill has been reviewed. Package resolution depends on the registry state and the package's current dependency graph at execution time. The `-y` option suppresses the installation confirmation that might otherwise alert the user to a download. This is a supply-chain weakness rather than evidence that the named package is currently malicious. The risk is that a compromised future release, dependency, package-maintainer account, registry response, or local package-resolution environment could cause unreviewed code to execute. ### Attack Path 1. A user copies the recommended MCP configuration. 2. The MCP server is started. 3. `npx -y` resolves the package from the configured package registry. 4. It downloads a package version that was not fixed during review. 5. Package or dependency code executes locally. 6. The process receives access to the wiki directory supplied as the filesystem server's allowed directory. 7. A compromised package can read, modify, or transmit wiki data and may access other resources permitted to the process unless additional OS sandboxing is present. ### Impact Assessment A compromised dependency would execute with the privileges of the user starting the MCP server. At minimum, the documented configuration intentionally grants access to the wiki directory, which may contain client details, account identifie ...[truncated 333 chars]
Remediation
View remediation
", ""] ``` 2. Prefer installing dependencies in advance through a committed lockfile. 3. Configure MCP to execute a fixed local binary from the reviewed installation rather than downloading code during startup. 4. Use registry integrity verification and retain package checksums or provenance information. 5. Disable lifecycle scripts during installation where compatible with the dependency. 6. Run the MCP server in a restricted OS account or sandbox with: - Access only to the wiki root - No unnecessary credentials - Restricted outbound networking - Read-only access where writes are not required 7. Establish a controlled dependency-update process that includes security review before changing the pinned version. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (28)

YARA rule 'agent_skill_credential_exfiltration_webhook': AI agent skill credential harvesting followed by webhook or external exfiltration [agent_skills]

Critical
Category
YARA Match
Confidence
85% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · scripts/lint.py (reported line 25)May include surrounding context.

python
$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 的标�

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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 · README.md (reported line 37)May include surrounding context.

md
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.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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 · README.md (reported line 155)May include surrounding context.

md
### 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`.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · README.md (reported line 241)May include surrounding context.

md
# 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 / ...)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · README.md (reported line 250)May include surrounding context.

md
# 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 / ...)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

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.

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/lint.py (reported line 25)May include surrounding context.

python
推送通知?自行在 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

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.