Back to skill

Security audit

微信公众号文章自动生成发布

Security checks for vulnerabilities and agentic risk

Overview

This WeChat publishing skill mostly does what it says, but it asks users to trust an unexplained fixed IP address and stores account secrets in a weak local file setup.

Review before installing. Do not add 112.8.202.216 to your WeChat IP allowlist unless the publisher clearly proves why it is needed; normally you should allow only the actual egress IP of the machine running the script. Keep AppSecret out of repositories and shared workspaces, restrict the credential file permissions, and confirm each draft submission before running publish.py.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
SKILL.md:31
Finding

Unnecessary Authorization of a Fixed External IP Address

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:31-33, SKILL.md:157; references/credentials_guide.md:22-29; references/api_ref.md:85
Vulnerability Type: Violation of least privilege through an unnecessary network allowlist entry
Risk Level: Medium

Vulnerable Documentation

SKILL.md:31-33:

markdown
2. **Add an IP allowlist entry**
   - On the same page, locate the IP allowlist settings
   - Add the server egress IP: `112.8.202.216`
   - Otherwise, the API will return error 40164

Equivalent instructions are repeated in references/credentials_guide.md:22-29, and the same address is presented as the solution for error 40164 in references/api_ref.md:85.

Technical Analysis

The Skill directs every user to authorize the fixed external IP address 112.8.202.216 in the WeChat account's API allowlist. However, the reviewed scripts make direct HTTPS requests from the local execution environment to https://api.weixin.qq.com. They do not use a proxy, hosted publishing service, callback, or other component associated with the documented fixed IP.

Consequently, the address that normally needs authorization is the actual egress IP of the machine running the scripts, not an unexplained shared address. Adding the fixed address expands the account's trusted network boundary beyond what is required by the implementation.

This issue does not independently disclose credentials or grant immediate account access. Exploitation additionally requires possession of the account's AppID and AppSecret, an access token, or another applicable credential. Nevertheless, the instruction removes one layer of source-network restriction for requests originating from that address.

Attack Path

  1. A user follows the Skill's mandatory setup instructions.
  2. The user adds 112.8.202.216 to the WeChat API allowlist.
  3. The operator of that address, or an attacker who compromises infrastructure using it, gains ...[truncated 878 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove every instruction that tells users to authorize 112.8.202.216.
  2. Instruct users to determine the actual public egress IP of the environment where the Python scripts will run.
  3. Tell users to authorize only that address and to remove obsolete allowlist entries after infrastructure changes.
  4. If the fixed address belongs to an intended hosted service, clearly document:
    • The service owner and operational purpose.
    • Why local execution routes through that service.
    • What credentials and content the service processes.
    • Data retention and access-control policies.
    • How users can avoid the hosted service.
  5. Make any hosted workflow explicitly optional rather than requiring all users to trust a shared external address.
  6. Add troubleshooting guidance that distinguishes local execution, dynamic egress IPs, NAT gateways, and intentionally hosted execution.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/publish.py:40
Finding

High-Value AppSecret Stored in a Predictable Plaintext File Without Permission Validation

Content
View full analysis

Vulnerability Details

File Location: scripts/publish.py:40-53; scripts/upload_cover.py:25-33; configuration instructions in SKILL.md:35-42
Vulnerability Type: Insecure local credential storage
Risk Level: Medium

Vulnerable Code

scripts/publish.py:40-53:

python
def load_credentials():
    """Read WeChat Official Account credentials"""
    if not os.path.exists(CREDENTIALS_FILE):
        raise FileNotFoundError(
            f"Credential file not found: {CREDENTIALS_FILE}\n"
            f"Create a JSON file containing appid and appsecret in the working directory"
        )

    with open(CREDENTIALS_FILE, "r", encoding="utf-8") as f:
        creds = json.load(f)

    if "appid" not in creds or "appsecret" not in creds:
        raise ValueError("The credential file must contain appid and appsecret fields")

    return creds["appid"], creds["appsecret"]

The corresponding implementation in scripts/upload_cover.py:25-33 is:

python
def load_credentials():
    if not os.path.exists(CREDENTIALS_FILE):
        raise FileNotFoundError(f"Credential file not found: {CREDENTIALS_FILE}")

    with open(CREDENTIALS_FILE, "r", encoding="utf-8") as f:
        creds = json.load(f)

    return creds["appid"], creds["appsecret"]

Both scripts use the predictable relative path configured as:

python
CREDENTIALS_FILE = "wechat_credentials.json"

Technical Analysis

The Skill requires the AppID and AppSecret to be stored in a plaintext JSON file in the current working directory. The AppSecret is a reusable, high-value credential that can be exchanged for an access token.

The implementation does not:

  • Verify that the file is owned by the expected user.
  • Reject symbolic links or unexpected file types.
  • Check whether filesystem permissions restrict access to the owner.
  • Support an operating-system secret store.
  • Support environment-based secret i ...[truncated 1809 chars]
Remediation
View remediation

Remediation Suggestions

  1. Prefer an operating-system credential store or dedicated secret manager instead of a plaintext project file.
  2. Support environment-variable or file-descriptor-based secret injection for automated environments.
  3. If file-based storage must remain available:
    • Require owner-only permissions equivalent to 0600 on POSIX systems.
    • Verify file ownership before reading it.
    • Reject symbolic links and non-regular files.
    • Fail securely when permissions are too broad.
    • Store the file outside the project and working directories by default.
  4. Add wechat_credentials.json to a distributed .gitignore file.
  5. Provide a sanitized example such as wechat_credentials.example.json containing placeholders only.
  6. Avoid printing the AppSecret or access token in normal output, exceptions, or debug logs.
  7. Document immediate AppSecret rotation if the file is committed, shared, or otherwise exposed.
  8. Continue sending credentials only to the hardcoded official HTTPS endpoint and prevent runtime overrides from redirecting them to an untrusted host.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (33)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents an end-to-end WeChat publishing skill, but this code chunk implements only one narrow subtask: local draft JSON creation from Markdown. It performs no network/API interaction, no authentication, no media creation/compression, and no upload/submission to WeChat. That is a material gap between the claimed functionality and the actual behavior of the supplied code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

声明描述的是一个完整的公众号文章发布/草稿创建技能,但该代码片段的实际功能明显更窄,只负责封面图上传到永久素材,并获取 media_id。虽然代码确实包含 Access Token 获取,这属于声明流程中的一部分,但未看到 Markdown 文章处理、封面生成、图片压缩、永久素材之外的文章素材处理、草稿 JSON 构造或草稿提交等核心能力。因此该代码与声明的主功能范围存在实质性不一致,属于描述大于实际行为的能力不匹配。

Content

No source excerpt is available for this finding.

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 · SKILL.md (reported line 5)May include surrounding context.

md
name: wechat-publisher
description: >
  微信公众号一键发布技能。帮助用户将 Markdown 文章自动发布到公众号草稿箱,
  包括:Access Token 获取、封面图生成与压缩、永久素材上传、草稿 JSON 构造与提交。
  当用户要求"发布公众号"、"写公众号文章"、"公众号草稿"时触发。
agent_created: true
---

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 · SKILL.md (reported line 96)May include surrounding context.

md
name: wechat-publisher
description: >
  微信公众号一键发布技能。帮助用户将 Markdown 文章自动发布到公众号草稿箱,
  包括:Access Token 获取、封面图生成与压缩、永久素材上传、草稿 JSON 构造与提交。
  当用户要求"发布公众号"、"写公众号文章"、"公众号草稿"时触发。
agent_created: true
---

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 · references/api_ref.md (reported line 13)May include surrounding context.

md
name: wechat-publisher
description: >
  微信公众号一键发布技能。帮助用户将 Markdown 文章自动发布到公众号草稿箱,
  包括:Access Token 获取、封面图生成与压缩、永久素材上传、草稿 JSON 构造与提交。
  当用户要求"发布公众号"、"写公众号文章"、"公众号草稿"时触发。
agent_created: true
---

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

python
name: wechat-publisher
description: >
  微信公众号一键发布技能。帮助用户将 Markdown 文章自动发布到公众号草稿箱,
  包括:Access Token 获取、封面图生成与压缩、永久素材上传、草稿 JSON 构造与提交。
  当用户要求"发布公众号"、"写公众号文章"、"公众号草稿"时触发。
agent_created: true
---

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

python
name: wechat-publisher
description: >
  微信公众号一键发布技能。帮助用户将 Markdown 文章自动发布到公众号草稿箱,
  包括:Access Token 获取、封面图生成与压缩、永久素材上传、草稿 JSON 构造与提交。
  当用户要求"发布公众号"、"写公众号文章"、"公众号草稿"时触发。
agent_created: true
---

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

python
name: wechat-publisher
description: >
  微信公众号一键发布技能。帮助用户将 Markdown 文章自动发布到公众号草稿箱,
  包括:Access Token 获取、封面图生成与压缩、永久素材上传、草稿 JSON 构造与提交。
  当用户要求"发布公众号"、"写公众号文章"、"公众号草稿"时触发。
agent_created: true
---

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

python
name: wechat-publisher
description: >
  微信公众号一键发布技能。帮助用户将 Markdown 文章自动发布到公众号草稿箱,
  包括:Access Token 获取、封面图生成与压缩、永久素材上传、草稿 JSON 构造与提交。
  当用户要求"发布公众号"、"写公众号文章"、"公众号草稿"时触发。
agent_created: true
---

Credential Access

High
Category
Privilege Escalation
Confidence
89% confidence
Finding

The skill instructs users to place AppID and AppSecret in a local JSON file in the working directory, which normalizes direct credential handling by the agent. In a skill with file access and network behavior, this raises the risk of inadvertent secret exposure, misuse by other tools in the workspace, or accidental inclusion in logs/version control.

Content

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

  • 否则 API 会返回 40164 错误
  1. 创建凭证文件 在工作目录创建 wechat_credentials.json:
    json
    {
      "appid": "你的AppID",
    

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 · references/api_ref.md (reported line 6)May include surrounding context.

md
## 基础信息

- **API 域名**: `https://api.weixin.qq.com`
- **Access Token**: 每次调用前重新获取,有效期 7200 秒
- **必需前提**: 调用 IP 已在 mp.weixin.qq.com 后台加入白名单

## 核心 API 端点

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 · references/api_ref.md (reported line 54)May include surrounding context.

md
## 基础信息

- **API 域名**: `https://api.weixin.qq.com`
- **Access Token**: 每次调用前重新获取,有效期 7200 秒
- **必需前提**: 调用 IP 已在 mp.weixin.qq.com 后台加入白名单

## 核心 API 端点

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 · SKILL.md (reported line 164)May include surrounding context.

md
python publish.py <文章.md路径> <封面图路径> [摘要]

功能:
  1. 读取 wechat_credentials.json 获取 AppID 和 AppSecret
  2. 获取 Access Token
  3. 上传封面图到永久素材
  4. 将 Markdown 转换为微信草稿 JSON

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 · references/api_ref.md (reported line 84)May include surrounding context.

md
python publish.py <文章.md路径> <封面图路径> [摘要]

功能:
  1. 读取 wechat_credentials.json 获取 AppID 和 AppSecret
  2. 获取 Access Token
  3. 上传封面图到永久素材
  4. 将 Markdown 转换为微信草稿 JSON

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 · references/credentials_guide.md (reported line 35)May include surrounding context.

md
python publish.py <文章.md路径> <封面图路径> [摘要]

功能:
  1. 读取 wechat_credentials.json 获取 AppID 和 AppSecret
  2. 获取 Access Token
  3. 上传封面图到永久素材
  4. 将 Markdown 转换为微信草稿 JSON

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 · references/credentials_guide.md (reported line 71)May include surrounding context.

md
python publish.py <文章.md路径> <封面图路径> [摘要]

功能:
  1. 读取 wechat_credentials.json 获取 AppID 和 AppSecret
  2. 获取 Access Token
  3. 上传封面图到永久素材
  4. 将 Markdown 转换为微信草稿 JSON

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

python
python publish.py <文章.md路径> <封面图路径> [摘要]

功能:
  1. 读取 wechat_credentials.json 获取 AppID 和 AppSecret
  2. 获取 Access Token
  3. 上传封面图到永久素材
  4. 将 Markdown 转换为微信草稿 JSON

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

python
python publish.py <文章.md路径> <封面图路径> [摘要]

功能:
  1. 读取 wechat_credentials.json 获取 AppID 和 AppSecret
  2. 获取 Access Token
  3. 上传封面图到永久素材
  4. 将 Markdown 转换为微信草稿 JSON

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

python
python publish.py <文章.md路径> <封面图路径> [摘要]

功能:
  1. 读取 wechat_credentials.json 获取 AppID 和 AppSecret
  2. 获取 Access Token
  3. 上传封面图到永久素材
  4. 将 Markdown 转换为微信草稿 JSON

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

python
python publish.py <文章.md路径> <封面图路径> [摘要]

功能:
  1. 读取 wechat_credentials.json 获取 AppID 和 AppSecret
  2. 获取 Access Token
  3. 上传封面图到永久素材
  4. 将 Markdown 转换为微信草稿 JSON

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises and instructs use of file read/write and networked publishing behavior, but it declares no explicit tool scope or permissions. That creates an overbroad trust boundary: an agent/runtime may permit more access than users expect, especially because the skill handles local credential files and outbound API calls.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger phrases are broad enough to overlap with ordinary writing or publishing requests, increasing the chance of accidental activation. In this skill's context, misfire matters more because activation can lead to credential use, local file access, and outbound publication-related network actions on behalf of the user.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file title and all instructional content are written exclusively in Chinese, with no indication that users may choose another language or that the locale restriction is intentional and justified. This can violate a language/locale policy when a skill or reference material imposes one language by default without user opt-in.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · references/api_ref.md (reported line 49)May include surrounding context.

$body = $memStream.ToArray() $memStream.Close()

$url = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=$token&type=image" $resp = Invoke-WebRequest -Uri $url -Method POST -Body $body -ContentType "multipart/form-data; boundary=$boundary" $resp.Content

text

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code file contains natural-language strings that impose a specific language for usage and operational output. Under the policy, forcing a language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly justified.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.