Back to skill

Security audit

Wechat Content Studio

Security checks for vulnerabilities and agentic risk

Overview

This WeChat content skill is mostly purpose-aligned, but it handles publishing credentials unsafely and can install unpinned global packages automatically.

Install only if you are comfortable reviewing scripts before use, managing WeChat credentials carefully, and approving any package installation yourself. Do not put real app secrets on the command line, rotate any secret that has appeared in logs or transcripts, and review drafts before publishing.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
Findings (4)

T01 · Skill Instruction Hijacking

Warning
Location
SKILL.md:138
Finding

Mandatory Promotional Content Injection into Generated Articles

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 138-152
Vulnerability Type: Persistent output manipulation through Skill instructions
Risk Level: Medium

Vulnerable Instruction

The article structure requires every generated article to contain a fixed footer. Translated from the source instruction:

markdown
[Fixed footer]
That is all. Since you have read this far, if you liked it, please like,
mark as recommended, and share it.
> / Author: XXX

Technical Analysis

The Skill defines this footer as a fixed component rather than an optional example. When the Skill is loaded, the agent is instructed to append engagement solicitation and an author-attribution field to generated articles, even when the user did not request either element.

This is a form of Skill instruction hijacking because the Skill alters the expected output contract and introduces stable promotional content. The placeholder attribution can also become misleading if it is retained or populated without explicit user approval.

Attack Path

  1. A user activates the Skill and asks it to generate a WeChat article.
  2. The agent follows the mandatory structure in SKILL.md.
  3. The fixed engagement solicitation and author attribution are appended automatically.
  4. If the user publishes the generated content without carefully reviewing the footer, unsolicited promotional language or inaccurate attribution is distributed publicly.

Impact Assessment

The issue does not grant operating-system privileges or expose credentials. Its impact is confined to generated content and the agent's current output behavior.

Potential consequences include:

  • Publication of promotional text not requested by the user.
  • Misleading or incorrect author attribution.
  • Reputational damage to the user or publishing account.
  • Loss of user control over the final article format.
Remediation
View remediation

Remediation Suggestions

  • Remove the mandatory fixed-footer requirement.
  • Treat engagement calls to action and attribution as optional templates.
  • Require the user to provide or explicitly approve an author name.
  • Omit promotional language by default.
  • Add a final publication preview that clearly identifies automatically inserted content.
  • Ensure that user instructions about tone, attribution, and footer content take precedence over style templates.

T08 · Insecure Dependencies

Error
Location
scripts/publish_and_verify.py:22
Finding

Automatic Installation of an Unpinned Global npm Package

Content
View full analysis

Vulnerability Details

File Location: scripts/publish_and_verify.py, lines 22-30
Vulnerability Type: Unsafe runtime dependency installation
Risk Level: High

Vulnerable Code

python
def check_wenyan() -> bool:
    if shutil.which("wenyan") is None:
        try:
            subprocess.run(
                ["npm", "install", "-g", "@wenyan-md/cli"],
                check=True,
                capture_output=False
            )
        except (subprocess.CalledProcessError, FileNotFoundError):
            return False
    return True

Technical Analysis

The publishing workflow automatically installs the latest available version of @wenyan-md/cli when the wenyan executable is absent. The package version is not pinned, no integrity hash is verified, and installation occurs globally.

npm packages may execute lifecycle scripts during installation. Consequently, the effective code executed by the Skill can change after the Skill itself has been audited. A compromised maintainer account, malicious package release, or upstream dependency compromise could result in arbitrary code execution under the privileges of the user running the Skill.

Global installation also expands the scope of modification beyond the project directory. After installation, the package is invoked with WeChat credentials placed in its environment by publish(), increasing the sensitivity of the trust relationship.

Attack Path

  1. An attacker compromises the npm package, one of its dependencies, or its publication channel.
  2. The attacker publishes a malicious version under the same unpinned package name.
  3. A user invokes publish_and_verify.py on a system where wenyan is not installed.
  4. npm install -g @wenyan-md/cli retrieves the current malicious release.
  5. Malicious npm lifecycle code executes with the invoking user's privileges.
  6. The installed executable can subsequently receive `WECHA ...[truncated 812 chars]
Remediation
View remediation

Remediation Suggestions

  • Do not automatically install dependencies during publication.
  • Require explicit user approval before any package installation.
  • Pin @wenyan-md/cli to a reviewed version.
  • Use a project-local dependency instead of npm install -g.
  • Commit and enforce a lockfile with integrity metadata.
  • Install with lifecycle scripts disabled where functionality permits.
  • Verify the package publisher, provenance, and integrity before execution.
  • Execute the publication tool with a minimal environment containing only the credentials it strictly requires.
  • Consider isolating the publisher in a restricted container or subprocess sandbox.

T08 · Insecure Dependencies

Error
Location
references/hv-analysis-methodology.md:164
Finding

Unpinned Python Installation Bypasses System Package Protections

Content
View full analysis

Vulnerability Details

File Location: references/hv-analysis-methodology.md, lines 164-168
Vulnerability Type: Unsafe dependency installation guidance
Risk Level: High

Vulnerable Instruction

bash
pip install weasyprint markdown --break-system-packages
python scripts/md_to_pdf.py input.md output.pdf \
  --title "Research Subject" \
  --author "Horizontal-Vertical Analysis"

Technical Analysis

The documented PDF workflow instructs users or agents to install unpinned Python packages while using --break-system-packages. That option deliberately bypasses protections for externally managed Python environments.

Neither dependency has a version constraint or hash. The downloaded package contents can therefore change after the Skill review. Installation-time package code and dependency resolution may execute or introduce compromised components. Bypassing system-package protections also creates a risk of replacing distribution-managed libraries and destabilizing unrelated applications.

The command then invokes scripts/md_to_pdf.py, but that file is not present in the audited project tree. This makes the documented workflow incomplete and may encourage users or agents to obtain the missing script from an unaudited source.

Attack Path

  1. An attacker compromises one of the named packages, a transitive dependency, or the package distribution channel.
  2. A user requests PDF report generation.
  3. The agent or user follows the installation command from the methodology document.
  4. pip resolves and installs the current unpinned package versions.
  5. --break-system-packages permits changes to an externally managed Python environment.
  6. Malicious installation code executes, or compromised libraries are installed for later execution.
  7. The user may additionally retrieve the missing md_to_pdf.py script from an untrusted source to complete the documented workflow.

Impact Assessment

...[truncated 536 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove --break-system-packages from the instructions.
  • Create and use an isolated virtual environment.
  • Pin all direct and transitive dependencies to reviewed versions.
  • Require hashes using a locked requirements file.
  • Include the referenced scripts/md_to_pdf.py in the project and audit it.
  • Do not instruct users to retrieve missing scripts from external sources.
  • Prefer reproducible package installation through a reviewed lockfile.
  • Run PDF conversion in a restricted environment with no access to unrelated secrets.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/add.py:26
Finding

WeChat Secrets Are Exposed Through Process Arguments and Standard Output

Content
View full analysis

Vulnerability Details

File Location: scripts/add.py, lines 26-31; scripts/get.py, lines 14-28; SKILL.md, lines 287-296
Vulnerability Type: Plaintext credential disclosure
Risk Level: High

Vulnerable Code and Instructions

The documented credential setup passes the secret directly as a command-line argument:

bash
python scripts/add.py wechat "WeChat Official Account" \
  appid=YOUR_APPID \
  appsecret=YOUR_APPSECRET

add.py prints every stored field immediately after saving it:

python
def add(key, name, **fields):
    data = load()
    if key not in data:
        data[key] = {"name": name}
    else:
        data[key]["name"] = name
    for k, v in fields.items():
        data[key][k] = v
    save(data)
    print(f"[OK] {key} ({name})")
    printFields(data[key])

def printFields(obj, indent=2):
    for k, v in obj.items():
        print("  " * indent + f"{k}: {v}")

get.py also prints requested secret values or every field in a credential record:

python
def get(key, field=None):
    data = load()
    if key not in data:
        return None

    if field:
        val = data[key].get(field)
        if val is None:
            return None
        print(val)
        return val
    else:
        for k, v in data[key].items():
            print(f"  {k}: {v}")
        return data[key]

Technical Analysis

Passing appsecret in command-line arguments can expose it through shell history, process inspection interfaces, debugging tools, job metadata, and command audit logs.

After receiving the secret, add.py prints the complete credential record without redaction. get.py similarly exposes either an individual field or all fields. These outputs may be captured by terminal recording, CI logs, orchestration systems, Agent transcripts, or monitoring infrastructure.

The underlying secrets file is changed to owner-read/wr ...[truncated 1645 chars]

Remediation
View remediation

Remediation Suggestions

  • Never accept secrets directly through command-line arguments.
  • Read secrets using hidden interactive input such as Python's getpass.
  • Prefer an operating-system keychain or dedicated secret manager.
  • Redact fields whose names contain values such as secret, token, password, or key.
  • Do not print complete credential records after storage.
  • Make get.py return masked values by default.
  • Require an explicit, separately authorized reveal operation for plaintext access.
  • Prevent secrets from being written to Agent transcripts or CI logs.
  • Preserve restrictive file permissions and create the file atomically with secure permissions.
  • Rotate any WeChat secret that may already have appeared in shell history, logs, or transcripts.
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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (46)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Deletion of credential entries from a local secrets file is a destructive privileged action that is not apparent from the skill's high-level content-studio description. A user invoking a writing tool would not reasonably expect it to include secret deletion utilities, creating risk of accidental or unauthorized credential loss.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Deletion of credential entries from a local secrets file is a destructive privileged action that is not apparent from the skill's high-level content-studio description. A user invoking a writing tool would not reasonably expect it to include secret deletion utilities, creating risk of accidental or unauthorized credential loss.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Deletion of credential entries from a local secrets file is a destructive privileged action that is not apparent from the skill's high-level content-studio description. A user invoking a writing tool would not reasonably expect it to include secret deletion utilities, creating risk of accidental or unauthorized credential loss.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

Deletion of credential entries from a local secrets file is a destructive privileged action that is not apparent from the skill's high-level content-studio description. A user invoking a writing tool would not reasonably expect it to include secret deletion utilities, creating risk of accidental or unauthorized credential loss.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

Deletion of credential entries from a local secrets file is a destructive privileged action that is not apparent from the skill's high-level content-studio description. A user invoking a writing tool would not reasonably expect it to include secret deletion utilities, creating risk of accidental or unauthorized credential loss.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Deletion of credential entries from a local secrets file is a destructive privileged action that is not apparent from the skill's high-level content-studio description. A user invoking a writing tool would not reasonably expect it to include secret deletion utilities, creating risk of accidental or unauthorized credential loss.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Deletion of credential entries from a local secrets file is a destructive privileged action that is not apparent from the skill's high-level content-studio description. A user invoking a writing tool would not reasonably expect it to include secret deletion utilities, creating risk of accidental or unauthorized credential loss.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger phrases include very broad natural-language activators such as '写稿子', '帮我研究一下', and '深度调研', which are likely to match routine conversation. In a skill that can access credentials, write files, use shell, and make network requests, ambiguous activation materially raises the chance of unintended execution.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The skill explicitly promotes storing WeChat app credentials in a local secrets file and includes helper scripts for secret management. In the context of a broadly triggered content skill with shell and filesystem access, credential access is especially dangerous because compromise or misuse can expose publication credentials and enable unauthorized actions on the user's account.

Content

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

凭证配置

方式1:secrets.json(推荐)

bash
python scripts/add.py wechat "微信公众号" appid=YOUR_APPID appsecret=YOUR_APPSECRET

Vague Triggers

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger list includes very broad, everyday phrases like '研究一下', '帮我分析', and '深度研究', which can cause the skill to activate in contexts far beyond the author's intended scope. In an agent environment, over-broad invocation can silently route ordinary user requests into a heavy workflow that performs web research, spawns sub-agents, and prepares long-form outputs, increasing the risk of unintended external calls, data exposure, and user confusion.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The script is explicitly wired to a secrets file path under the user's home directory, indicating direct credential access capability. In a content-studio skill, this is more dangerous because it broadens the skill from article publishing into generalized secret retrieval, which could expose API keys, tokens, or other unrelated credentials if misused.

Content

Scanner excerpt · scripts/get.py (reported line 6)May include surrounding context.

python
import sys; sys.stdout.reconfigure(encoding='utf-8')
import os, json, stat

SECRETS_FILE = os.path.expanduser("~/.openclaw/workspace/secrets.json")

def load():
    if os.path.exists(SECRETS_FILE):

Credential Access

High
Category
Privilege Escalation
Confidence
87% confidence
Finding

The code is explicitly designed to access a centralized secrets file in the user's home workspace, which is highly sensitive material. In the context of an agent skill for a content/publishing pipeline, direct secret-file access is more dangerous because such skills may run in automation contexts where users do not expect credential enumeration, making credential discovery and subsequent misuse easier.

Content

Scanner excerpt · scripts/list.py (reported line 6)May include surrounding context.

python
import sys; sys.stdout.reconfigure(encoding='utf-8')
import os, json, stat

SECRETS_FILE = os.path.expanduser("~/.openclaw/workspace/secrets.json")

def load():
    if os.path.exists(SECRETS_FILE):

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

The script is explicitly designed to access a local secrets.json file to retrieve publishing credentials. Accessing local secret stores is security-sensitive behavior, and in an agent skill it becomes more dangerous because it broadens the skill's authority beyond the immediate user-supplied article input.

Content

Scanner excerpt · scripts/publish_and_verify.py (reported line 35)May include surrounding context.

python
def load_credentials() -> tuple[str, str]:
    """优先从 secrets.json 读取凭证,fallback 到 TOOLS.md"""
    app_id, app_secret = "", ""
    secrets_file = os.path.expanduser("~/.openclaw/workspace/secrets.json")

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

Checking for the existence of a secrets file is part of a credential discovery flow that probes the local filesystem for sensitive material. This is risky in agent environments because it normalizes hidden secret access rather than requiring explicit user-provided credentials.

Content

Scanner excerpt · scripts/publish_and_verify.py (reported line 37)May include surrounding context.

python
def load_credentials() -> tuple[str, str]:
    """优先从 secrets.json 读取凭证,fallback 到 TOOLS.md"""
    app_id, app_secret = "", ""
    secrets_file = os.path.expanduser("~/.openclaw/workspace/secrets.json")

    # 优先从 secrets.json 读取
    if os.path.isfile(secrets_file):

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

Opening and parsing secrets.json directly accesses sensitive credentials from disk. If this skill is reused in broader environments, such behavior can expose or misuse credentials outside the user's immediate intent, especially when combined with later subprocess/network actions.

Content

Scanner excerpt · scripts/publish_and_verify.py (reported line 39)May include surrounding context.

python
app_id, app_secret = "", ""
    secrets_file = os.path.expanduser("~/.openclaw/workspace/secrets.json")

    # 优先从 secrets.json 读取
    if os.path.isfile(secrets_file):
        with open(secrets_file, encoding="utf-8") as f:
            secrets = json.load(f)

Credential Access

High
Category
Privilege Escalation
Confidence
92% confidence
Finding

This branch confirms successful retrieval of WeChat credentials from secrets.json and proceeds to use them, demonstrating active secret consumption. In context, the skill's publishing purpose explains why credentials are needed, but silently sourcing them from local files still increases the risk of unauthorized secret use.

Content

Scanner excerpt · scripts/publish_and_verify.py (reported line 47)May include surrounding context.

python
app_id = secrets["wechat"].get("appid", "")
            app_secret = secrets["wechat"].get("appsecret", "")
            if app_id and app_secret:
                print(f"{YELLOW}从 secrets.json 读取微信公众号凭证{NC}")
                return app_id, app_secret

    # Fallback 到 TOOLS.md

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/publish_and_verify.py (reported line 93)May include surrounding context.

python
print("")

    app_id, app_secret = load_credentials()
    env = os.environ.copy()
    if app_id:
        env["WECHAT_APP_ID"] = app_id
    if app_secret:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

User-controlled parameters are incorporated into a shell-executed command, creating a classic tool-parameter abuse risk. Because this skill accepts a file path and optional style arguments, a malicious or malformed input on Windows could potentially alter command execution and run unintended commands.

Content

Scanner excerpt · scripts/publish_and_verify.py (reported line 106)May include surrounding context.

python
def cmd_escape(s):
            return str(s).replace("^", "^^").replace("&", "^&").replace("%", "^%").replace("<", "^<").replace(">", "^>").replace("|", "^|").replace('"', '""')
        cmd_str = " ".join(f'"{cmd_escape(p)}"' for p in cmd_parts)
        result = subprocess.run(cmd_str, check=False, env=env, shell=True)
    else:
        # Unix: use list form without shell
        result = subprocess.run(cmd_parts, check=False, env=env)

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

python
import sys; sys.stdout.reconfigure(encoding='utf-8')
import os, json, stat

SECRETS_FILE = os.path.expanduser("~/.openclaw/workspace/secrets.json")

def load():
    if os.path.exists(SECRETS_FILE):

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

python
import sys; sys.stdout.reconfigure(encoding='utf-8')
import os, json, stat

SECRETS_FILE = os.path.expanduser("~/.openclaw/workspace/secrets.json")

def load():
    if os.path.exists(SECRETS_FILE):

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
97% confidence
Finding

The skill advertises and relies on environment variables, shell commands, network access, and filesystem writes, but does not declare an explicit tool scope such as permissions or allowed-tools. That creates an overbroad execution surface where an agent may invoke sensitive capabilities without clear user-visible constraints, increasing the risk of unintended command execution, remote requests, and local data modification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The publishing workflow instructs the agent to generate assets, prepare frontmatter, publish to a draft box, verify indexing, and track data, but it does not clearly warn the user that credentials will be used and that remote publication-related actions will occur. For a workflow touching external accounts and persistent content, lack of informed-consent warnings can lead to accidental publication or unauthorized account operations.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The hv-analysis flow is activated by an ambiguous phrase and described as automatically performing online search. Because the phrase is conversational and the action leads to network activity, users may trigger external requests without realizing a sensitive workflow has started.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill advertises automatic online research and PDF generation but does not present user-facing warnings or consent boundaries around network access, third-party data collection, package installation, or file creation. This is risky because a casually triggered skill could perform external actions or transform user-provided material into local artifacts without clear notice, which is especially concerning given the broad triggers elsewhere in the file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file presents all headings, examples, and instructions exclusively in Chinese, which effectively forces a single language/locale on users. Under the stated policy, language constraints should either offer user choice or be clearly justified as region-specific, neither of which appears in the file.

Content

No source excerpt is available for this finding.