Back to skill

Security audit

Wechat Publisher

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims, but it handles WeChat account credentials and stores access tokens locally without protective file permissions.

Install only if you are comfortable giving the skill WeChat Official Account API credentials and having article text, metadata, and selected images uploaded to WeChat. Prefer environment variables or a protected secrets manager, keep config.json and .token_cache.json out of source control, restrict token-cache permissions, and review generated drafts before publishing.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/get_token.py:54
Finding

Plaintext Access Token Cache Without Restrictive File Permissions

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/md_to_html.py:92
Finding

Unsanitized Markdown and URL Values Can Inject Unsafe Draft HTML

Content
View full analysis
\\1', text) text = re.sub(r'__(.+?)__', f'\\1', text) # Italic text = re.sub(r'\*(.+?)\*', f'\\1', text) # Inline code text = re.sub(r'`(.+?)`', f'\\1', text) # Links text = re.sub(r'\[(.+?)\]\((.+?)\)', r'\1', text) return text ``` Image source and alternative-text values are also interpolated without escaping: ```python # Image m = re.match(r'^!\[([^\]]*)\]\(([^)]+)\)', stripped) if m: alt, src = m.group(1), m.group(2) html_lines.append(f'{alt}') continue ``` Image-map values are inserted into `src` attributes without URL or attribute validation: ```python def apply_image_map(html: str, image_map: dict) -> str: """Replace local image filenames with WeChat CDN URLs.""" for local_name, wx_url in image_map.items(): html = html.replace(f'src="{local_name}"', f'src="{wx_url}"') # Also handle paths html = re.sub( rf'src="[^"]*{re.escape(local_name)}"', f'src="{wx_url}"', html ) return html ``` When the optional `markdown` package is installed, generated HTML is accepted without a sanitization pass: ```python if try_import_markdown(): import markdown html = markdown.markdown(md_text, extensions=["extra"]) # Apply inline sty ...[truncated 2932 chars]
Remediation
View remediation
` and event-handler attributes. - Unsafe URL schemes. - Malicious image-map values. - Encoded or mixed-case scheme and hostname bypasses. ]]>
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (29)

Tainted flow: 'req' from os.environ.get (line 46, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/get_token.py (reported line 48)May include surrounding context.

python
}).encode()
    req = urllib.request.Request(TOKEN_URL, data=payload,
                                  headers={"Content-Type": "application/json"}, method="POST")
    with urllib.request.urlopen(req) as resp:
        data = json.loads(resp.read())
    if "errcode" in data and data["errcode"] != 0:
        print(f"ERROR: WeChat API error: {data}", file=sys.stderr)

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

Manual / scripted usage

bash
# Get access token
python3 scripts/get_token.py

# Upload cover image → get thumb_media_id

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

Manual / scripted usage

bash
# Get access token
python3 scripts/get_token.py

# Upload cover image → get thumb_media_id

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a full WeChat draft publishing skill: managing API tokens, uploading images to WeChat CDN, converting Markdown, and creating a draft in the公众号 draft box. The supplied code chunk does only one subset task: Markdown-to-HTML conversion with optional substitution of image URLs from a JSON mapping file. It performs no network access, no authentication, no token handling, no CDN upload, and no draft creation via API. Because the actual behavior is materially narrower and lacks the core publishing/API capabilities described, this is a clear description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code’s core behavior is narrower than the declared description. It does perform token retrieval and draft creation for a WeChat Official Account, which aligns partially with the stated purpose. However, this script only accepts HTML input (--html or --html-content) and requires a preexisting thumb_media_id; it does not convert Markdown to HTML, discover or upload local images, or generate/upload image assets to WeChat CDN. Therefore, the declared description overstates the implemented capabilities of this code chunk.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
78% confidence
Finding

The skill states that access tokens are cached in a local .token_cache.json file, which creates a credential-handling risk if file permissions are weak, the workspace is shared, or logs/backups expose the cache. While token caching is operationally common, storing bearer-style tokens on disk without documented protections can enable account misuse if the file is read by another process or user.

Content

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

md
## Notes

- Access tokens are cached in `.token_cache.json` (auto-refreshed when expired)
- WeChat only accepts images hosted on WeChat CDN — always upload images first
- The draft is saved but NOT published; user must publish manually from MP backend or via `/cgi-bin/freepublish/submit`
- Subscription accounts (订阅号) may have limited publishing frequency (once per day/week)

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

python
#!/usr/bin/env python3
"""
Get (and cache) WeChat Official Account Access Token.
Usage: python3 get_token.py
Output: prints the access_token string to stdout
Config: reads APPID and APPSECRET from ../config.json or env vars WX_APPID / WX_APPSECRET

Tainted flow: 'req' from pathlib.Path.read_bytes (line 52, file read) → urllib.request.urlopen (network output)

High
Category
Data Flow
Confidence
80% confidence
Finding

File contents flow to a network sink. This may indicate data exfiltration of sensitive files.

Content

Scanner excerpt · scripts/upload_img.py (reported line 55)May include surrounding context.

python
req = urllib.request.Request(url, data=body,
                                  headers={"Content-Type": f"multipart/form-data; boundary={boundary}"},
                                  method="POST")
    with urllib.request.urlopen(req) as resp:
        data = json.loads(resp.read())

    if "errcode" in data and data["errcode"] != 0:

Tainted flow: 'req' from pathlib.Path.read_bytes (line 48, file read) → urllib.request.urlopen (network output)

High
Category
Data Flow
Confidence
80% confidence
Finding

File contents flow to a network sink. This may indicate data exfiltration of sensitive files.

Content

Scanner excerpt · scripts/upload_thumb.py (reported line 51)May include surrounding context.

python
req = urllib.request.Request(url, data=body,
                                  headers={"Content-Type": f"multipart/form-data; boundary={boundary}"},
                                  method="POST")
    with urllib.request.urlopen(req) as resp:
        data = json.loads(resp.read())

    if "errcode" in data and data["errcode"] != 0:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README promotes an automated workflow that uploads article content and images to WeChat services, but it does not clearly warn users that local files and article data will be transmitted to a third-party platform. In a publishing skill, this omission can cause accidental disclosure of private, unpublished, or sensitive content because users may assume processing is local or not appreciate the full data flow.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill directs execution of Python scripts, reads local files, writes temporary files, uses environment variables for credentials, and performs networked uploads, but it declares no explicit tool scope or permission boundaries. This increases the chance an agent will invoke sensitive capabilities without clear user consent or policy enforcement, especially because the workflow handles local content and secrets.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill instructs the user to upload article text and local images to WeChat, but it does not prominently disclose that local files and potentially sensitive content will be transmitted to a third-party service. In an agent setting, missing disclosure can cause unintended exfiltration of proprietary drafts, personal data, or unpublished media.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The reference shows storing long-lived WeChat app credentials in a local config file and environment variables without any warning about secret handling, file permissions, rotation, or avoiding commits to source control. In a skill that manages authentication tokens for a production publishing API, this omission can lead users to expose app secrets, enabling unauthorized API access and account abuse.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file describes conversion specifically to 'WeChat-compatible HTML' and embeds Chinese-platform-specific assumptions such as WeChat CDN URLs and Chinese font preferences. Because the script is framed as a general Markdown-to-HTML converter rather than clearly as a region-specific tool with opt-in locale selection, this can violate language/locale policy expectations.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest describes a WeChat publishing skill that handles token management, image upload, content conversion, and draft creation. In this file, token retrieval is implemented by launching another Python process via subprocess, which adds process-execution capability beyond the obvious needs of publishing a draft.

Content

No source excerpt is available for this finding.

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

md
import json, sys, urllib.request
from pathlib import Path

UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/material/add_material"

def get_token():
    import subprocess

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

md
import json, sys, urllib.request
from pathlib import Path

UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/material/add_material"

def get_token():
    import subprocess

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

md
import json, sys, urllib.request
from pathlib import Path

UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/material/add_material"

def get_token():
    import subprocess

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

md
import json, sys, urllib.request
from pathlib import Path

UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/material/add_material"

def get_token():
    import subprocess

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

md
import json, sys, urllib.request
from pathlib import Path

UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/material/add_material"

def get_token():
    import subprocess

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 · scripts/get_token.py (reported line 14)May include surrounding context.

python
import json, sys, urllib.request
from pathlib import Path

UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/material/add_material"

def get_token():
    import subprocess

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 · scripts/upload_draft.py (reported line 24)May include surrounding context.

python
import json, sys, urllib.request
from pathlib import Path

UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/material/add_material"

def get_token():
    import subprocess

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 · scripts/upload_img.py (reported line 14)May include surrounding context.

python
import json, sys, urllib.request
from pathlib import Path

UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/material/add_material"

def get_token():
    import subprocess

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 · scripts/upload_thumb.py (reported line 14)May include surrounding context.

python
import json, sys, urllib.request
from pathlib import Path

UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/material/add_material"

def get_token():
    import subprocess

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/upload_draft.py (reported line 29)May include surrounding context.

python
def get_token():
    import subprocess
    result = subprocess.run(
        ["python3", Path(__file__).parent / "get_token.py"],
        capture_output=True, text=True
    )

Static analysis

No suspicious patterns detected.