Back to skill

Security audit

wechat-mp-publisher

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent WeChat publishing helper, but it handles unpublished articles and WeChat secrets through remote and shell-based flows that are not safely scoped or clearly protected.

Review this before installing. Use it only with an MCP server you control or fully trust, require HTTPS rather than the documented HTTP example, and assume the remote service can see unpublished articles and WeChat AppID/AppSecret. Avoid the legacy TOOLS.md setup, protect wechat.env with restrictive permissions, do not put shell commands in it, prefer a pinned/preinstalled publishing CLI over npx, and test with a low-risk account or draft workflow before using production credentials.

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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/publish-remote.sh:96
Finding
WeChat credentials and unpublished content may be transmitted over plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/publish-remote.sh:96-105`; related insecure endpoint guidance at `SKILL.md:53-67` **Vulnerability Type**: Plaintext transmission of sensitive credentials to a configurable remote service **Risk Level**: High ### Vulnerable Code ```bash # Construct Publish Arguments PUBLISH_ARGS=$(jq -n \ --arg file_id "$FILE_ID" \ --arg theme_id "$THEME_ID" \ --arg app_id "$WECHAT_APP_ID" \ --arg app_secret "$WECHAT_APP_SECRET" \ '{file_id: $file_id, theme_id: $theme_id, wechat_app_id: $app_id, wechat_app_secret: $app_secret}') # Call remote MCP PUBLISH_RES=$(mcporter call wenyan-mcp.publish_article --config "$MCP_CONFIG_FILE" --args "$PUBLISH_ARGS" 2>/dev/null) ``` The documented MCP configuration explicitly recommends an unencrypted HTTP endpoint: ```json { "mcpServers": { "wenyan-mcp": { "name": "Remote WeChat Assistant", "transport": "sse", "url": "http://<your-remote-server-ip>:3000/sse", "headers": { "X-API-Key": "<optional-api-key>" } } } } ``` ### Technical Analysis The remote publishing script places the WeChat AppID and AppSecret directly into the arguments sent to `wenyan-mcp.publish_article`. It also uploads the unpublished Markdown article through the same configurable MCP service. Remote processing is part of the declared functionality, so transmitting publishing data to a remote server is functionally expected. However, transmitting it over plaintext HTTP is not necessary. The script does not reject non-TLS endpoints or otherwise enforce transport security. The MCP endpoint is selected through `$HOME/.openclaw/mcp.json` or a user-specified configuration file. Consequently, the confidentiality of the credentials and article depends entirely on the selected endpoint and network path. ### Attack Path 1. A user follows the configuration example and sets the MCP URL to an `http://` endpoint. 2. The user invokes `scripts/publish-remote.s ...[truncated 969 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require MCP endpoints to use HTTPS with valid certificate verification. 2. Reject `http://` URLs before transmitting article data or credentials. 3. Clearly disclose that the remote MCP operator receives both unpublished content and WeChat credentials. 4. Prefer storing the WeChat credential on a trusted, administrator-controlled MCP server instead of sending the AppSecret with every publication request. 5. Use narrowly scoped, revocable credentials where the WeChat platform supports them. 6. Authenticate the MCP service and protect API keys with restrictive file permissions. 7. Provide endpoint identity verification or certificate pinning for high-assurance deployments. 8. Rotate the WeChat AppSecret immediately if it has previously been transmitted through an untrusted or plaintext endpoint. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/setup.sh:5
Finding
Legacy setup script reads credentials from the general OpenClaw workspace<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh:5-22` **Vulnerability Type**: Unnecessary access to a credential-bearing Agent workspace file **Risk Level**: Medium ### Vulnerable Code ```bash TOOLS_MD="$HOME/.openclaw/workspace/TOOLS.md" # Check whether TOOLS.md exists if [ ! -f "$TOOLS_MD" ]; then echo "TOOLS.md was not found: $TOOLS_MD" echo "" echo "Add the WeChat Official Account credentials to TOOLS.md:" echo "" echo "## WeChat Official Account" echo "" echo "export WECHAT_APP_ID=your_app_id" echo "export WECHAT_APP_SECRET=your_app_secret" exit 1 fi # Extract credentials from TOOLS.md WECHAT_APP_ID=$(grep "export WECHAT_APP_ID=" "$TOOLS_MD" | head -1 | sed 's/.*export WECHAT_APP_ID=//' | tr -d ' ') WECHAT_APP_SECRET=$(grep "export WECHAT_APP_SECRET=" "$TOOLS_MD" | head -1 | sed 's/.*export WECHAT_APP_SECRET=//' | tr -d ' ') ``` Related legacy guidance also appears in `example.md:31`: ```markdown 1. Configure credentials (TOOLS.md) ``` ### Technical Analysis The setup script reads WeChat credentials from the general OpenClaw workspace file at `$HOME/.openclaw/workspace/TOOLS.md`. Such a workspace document may contain configuration for multiple tools and may be available to broader Agent workflows. This access is not required by the current design. The primary documentation and publishing scripts use a dedicated `wechat.env` file in the Skill directory. Reading the broader workspace therefore exceeds the minimum access necessary to obtain the two WeChat values. The current extraction commands only return lines matching the specified WeChat variables; there is no confirmed extraction or transmission of unrelated credentials. Nevertheless, encouraging secrets to be stored in a broad workspace document unnecessarily expands their exposure. ### Attack Path 1. A user follows the legacy setup instructions and places the WeChat AppID and AppSecret in `TOOLS.md`. 2. The user sources or executes ...[truncated 870 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `scripts/setup.sh` if it is obsolete. 2. Remove all instructions that tell users to store credentials in `TOOLS.md`. 3. Use one dedicated credential source consistently, such as: - A permission-restricted `wechat.env` file. - An operating-system credential store. - A dedicated OpenClaw secret-management mechanism. 4. Set credential file permissions to owner read/write only, such as mode `0600`. 5. Avoid exporting credentials globally when they can instead be passed only to the required child process. 6. Clear sensitive environment variables after publication where practical. 7. Update `example.md`, `README.md`, and `SKILL.md` so they describe one consistent and isolated credential model. ]]>

T08 · Insecure Dependencies

Error
Location
scripts/publish.sh:26
Finding
Unpinned publishing package may be downloaded and executed at runtime through npx<![CDATA[ ## Vulnerability Details **File Location**: `scripts/publish.sh:26-31` **Vulnerability Type**: Unpinned runtime dependency execution **Risk Level**: High ### Vulnerable Code ```bash elif command -v npx &> /dev/null; then echo -e "${YELLOW}wenyan-cli is not installed; running it with npx...${NC}" WENYAN_CMD="npx @wenyan-md/cli" else echo -e "${RED}wenyan-cli and npx are not installed.${NC}" echo -e "${YELLOW}Install Node.js or run: npm install -g @wenyan-md/cli${NC}" exit 1 fi ``` The selected command is later executed as follows at `scripts/publish.sh:85`: ```bash $WENYAN_CMD publish -f "$file" -t "$theme" -h "$highlight" ``` ### Technical Analysis When a local `wenyan` executable is unavailable, the script falls back to `npx @wenyan-md/cli` without specifying an exact package version or verifying package integrity. This means the code executed during publication can differ from the code reviewed with the Skill. The effective dependency is resolved from the configured npm registry at runtime. A compromised package release, registry account, registry mirror, or local npm configuration could cause attacker-controlled package code to run. The package executes while WeChat credentials are exported in the environment and while the article path is available. Therefore, a compromised dependency would have access to high-value publishing data. ### Attack Path 1. The victim's system does not have the `wenyan` command installed. 2. The script detects `npx` and selects `npx @wenyan-md/cli`. 3. `check_env` loads and exports `WECHAT_APP_ID` and `WECHAT_APP_SECRET`. 4. The publication function invokes the unpinned package through `npx`. 5. A malicious or compromised package version executes with the victim's user privileges. 6. The package reads inherited credentials, article files, or other user-accessible resources and may transmit or misuse them. ### Impact Assessment A compromised dependency would execute with the privileges of t ...[truncated 480 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `@wenyan-md/cli` to an exact audited version. 2. Install dependencies during a separate, explicit setup step rather than during publication. 3. Use a lockfile and verify package integrity hashes. 4. Disable automatic runtime package installation. 5. Execute a known local binary from a controlled installation directory. 6. Document the expected package publisher, version, and integrity information. 7. Review dependency updates before changing the pinned version. 8. Minimize the environment passed to the publishing process so unrelated secrets are not inherited. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/publish-remote.sh:15
Finding
Credential configuration file is executed as arbitrary shell code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/publish-remote.sh:15-18` **Vulnerability Type**: Arbitrary command execution through unsafe configuration loading **Risk Level**: High ### Vulnerable Code ```bash # Load Configuration if [ -f "$CONFIG_FILE" ]; then source "$CONFIG_FILE" fi ``` `CONFIG_FILE` is defined at `scripts/publish-remote.sh:12`: ```bash CONFIG_FILE="${SKILL_ROOT}/wechat.env" ``` ### Technical Analysis The Bash `source` command does not parse a passive environment-data format. It executes the complete contents of the referenced file in the current shell. Although the documentation presents `wechat.env` as a file containing only `export` statements, the script performs no syntax validation, ownership check, or permission check before sourcing it. Any shell expression, command substitution, function definition, redirection, or executable command placed in the file will run before publication. This is particularly dangerous when the Skill directory is shared, downloaded from an untrusted source, writable by another account, or modified after installation. ### Attack Path 1. An attacker gains the ability to modify or replace the Skill's `wechat.env` file. 2. The attacker inserts an arbitrary shell command into that file. 3. The victim invokes `scripts/publish-remote.sh`. 4. Bash executes `source "$CONFIG_FILE"`. 5. The attacker's command runs immediately with the victim's user privileges. 6. The malicious command may access local files, credentials, article content, or network resources before the publishing operation begins. ### Impact Assessment Successful exploitation provides arbitrary command execution with the privileges of the user running the publishing script. The resulting scope can include: - Reading or modifying any user-accessible file. - Accessing the WeChat credentials contained in the same configuration file. - Accessing OpenClaw configuration files. - Stealing unpublished article content. - Execut ...[truncated 248 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not use `source` for credential files. 2. Parse only an explicit allowlist of supported keys: - `WECHAT_APP_ID` - `WECHAT_APP_SECRET` - `MCP_CONFIG_FILE`, if this setting must remain configurable 3. Reject unknown keys, command substitutions, shell metacharacters, and malformed lines. 4. Prefer a structured data format such as JSON and parse it with `jq`. 5. Verify that the credential file is owned by the invoking user. 6. Reject files writable by group or other users. 7. Require restrictive permissions such as mode `0600`. 8. Consider retrieving credentials from a secret manager rather than a shell-compatible file. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
A second material mismatch exists around undeclared credential/data handling: the skill presents itself as a remote publishing helper but does not clearly disclose all local/remote behaviors, while static analysis indicates possible access to local credential material not transparently described to the user. In a publishing skill that may process article drafts and account secrets, hidden or overstated behavior materially increases the risk of credential leakage and unintended data transmission.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
A second material mismatch exists around undeclared credential/data handling: the skill presents itself as a remote publishing helper but does not clearly disclose all local/remote behaviors, while static analysis indicates possible access to local credential material not transparently described to the user. In a publishing skill that may process article drafts and account secrets, hidden or overstated behavior materially increases the risk of credential leakage and unintended data transmission.

Credential Access

High
Category
Privilege Escalation
Content
使用本远程技能时,**必须将 MCP 服务所在公网 IP** 加入白名单,而**不是**你当前操作机器的 IP。

**为什么?**
- 所有的 API 请求(包括获取 Access Token、上传图文、上传素材)都是由 **远程 MCP 服务器** 发起的。
- 你本地的 OpenClaw 只负责发指令给 MCP,不直接与微信交互。
- 即使你在家里用动态 IP 也没关系,只要 MCP 服务器 IP 固定即可。
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README promotes remote HTTP publishing and emphasizes convenience and 'security isolation', but it does not clearly disclose that article content and sensitive runtime credentials are sent to a remote MCP service. This can mislead users into trusting the setup as local-only or low-risk, increasing the chance of credential exposure, content leakage, or publication through an untrusted intermediary.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill advertises shell-based setup and execution steps (`cp`, `nano`, `chmod`, running a publish script) but does not declare any explicit tool scope or allowed-tools boundary. That omission weakens least-privilege controls and can cause an agent to invoke shell capabilities more broadly than users expect, increasing the chance of unintended local command execution.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill promotes use of a remote HTTP MCP service but does not prominently warn that article content, metadata, and possibly operational context will be transmitted to a remote server. This is a meaningful security and privacy issue because users may send unpublished drafts or sensitive business content off-device without informed consent, especially since the example uses plain HTTP rather than HTTPS.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The suggested invocation phrase is broad ('帮我把 path/to/article.md 发布到公众号...') and lacks clear activation constraints, confirmations, or boundary checks. In practice this can cause the agent to trigger the skill for ambiguous requests and perform publication actions against local files or remote services without sufficient user intent verification.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The example content encourages credential setup and one-click publication to a real WeChat public account but does not warn that content and media will be transmitted to a remote service and may immediately affect a live account. In a publishing skill, this omission increases the chance of accidental posting, unintended data disclosure, or misuse by users who treat the example as harmless test content.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The file presents all troubleshooting guidance exclusively in Chinese, which can constitute a language/locale policy issue when no user opt-in or justification is provided. The content does not indicate that the skill is region-specific or that alternative language support is available.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script reads the full article content and sends it to a remote MCP service, then sends WeChat App ID and App Secret to the same remote service for publishing. Even if this is functionally intended, it creates a real confidentiality risk because sensitive content and credentials are disclosed to an external system without an explicit runtime warning, consent step, or clear trust boundary enforcement.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The script dynamically executes an external package through `npx`, which means unreviewed remote code can run at publish time. Although invoking a publishing CLI is aligned with the skill's purpose, the dynamic download/execution model expands trust to the npm supply chain and allows that package to access article content, environment variables, and the local system.

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding
The script falls back to executing `npx @wenyan-md/cli` without pinning a specific version, so each run may fetch and execute whatever package version is currently published. This creates a supply-chain risk: a compromised upstream package, typo-squatted dependency resolution, or unexpected breaking change could lead to arbitrary code execution in the user's environment with access to WeChat credentials and local files.

Natural-Language Policy Violations

Low
Confidence
85% confidence
Finding
The script description is written only in Chinese ("远程发布文章到微信公众号"), which imposes a specific language context without offering any user choice or bilingual explanation. Under the stated policy, forcing a language or locale without opt-in is a natural-language policy concern.

Intent-Code Divergence

Low
Confidence
76% confidence
Finding
The inline comment says credentials are sourced 'only specific vars to avoid polluting env', suggesting a constrained handling approach. In practice, the script exports both secrets as environment variables for downstream commands, which still populates the process environment and weakens the stated isolation intent.

Static analysis

No suspicious patterns detected.