Back to skill

Security audit

WeChat Article Multi Publisher

Security checks across malware telemetry and agentic risk

Overview

This is a disclosed WeChat publishing tool, but it deserves review because it can publish or delete WeChat account content and fetch/upload arbitrary URLs without strong safeguards.

Install only if you are comfortable giving the skill WeChat Official Account credentials and letting it create drafts, upload images, publish articles, and delete drafts when invoked. Use --dry-run first, verify the selected account and media_id before publishing or deleting, avoid untrusted article/image URLs, and keep config.json out of shared repositories.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
req = Path(__file__).resolve().parent / "requirements.txt"
    if not req.exists():
        raise RuntimeError(f"未找到依赖文件: {req}")
    subprocess.check_call([sys.executable, "-m", "pip", "install", "-r", str(req)])


def slugify(text: str) -> str:
Confidence
90% confidence
Finding
The script can invoke pip at runtime via `subprocess.check_call(...)` when `--install` is used. While arguments are passed safely as a list and there is no shell injection, allowing a skill to install dependencies on demand expands its execution scope and can fetch and execute arbitrary package installation code from external sources, which is risky in agent environments.

Tainted flow: 'image_url' from requests.post (line 766, network input) → requests.get (network output)

Medium
Category
Data Flow
Content
return media_id

    def upload_image_from_url(self, token: str, image_url: str) -> str:
        img = requests.get(image_url, timeout=self.timeout)
        img.raise_for_status()
        content_type = img.headers.get("Content-Type", "image/jpeg")
        if not content_type.startswith("image/"):
Confidence
95% confidence
Finding
`upload_image_from_url` performs `requests.get(image_url)` on a user-controlled URL, which creates a clear SSRF primitive. An attacker could cause the skill to make requests to internal services, cloud metadata endpoints, or other network locations reachable from the runtime and then relay the fetched content onward to WeChat.

Tainted flow: 'image_url' from requests.post (line 766, network input) → requests.get (network output)

Medium
Category
Data Flow
Content
return image_url

    def upload_content_image_from_url(self, token: str, image_url: str) -> str:
        img = requests.get(image_url, timeout=self.timeout)
        img.raise_for_status()
        content_type = img.headers.get("Content-Type", "image/jpeg")
        if not content_type.startswith("image/"):
Confidence
95% confidence
Finding
`upload_content_image_from_url` also fetches a user-controlled URL with `requests.get`, creating a second SSRF path. Because the function uploads the fetched response into article content handling, it can be abused to reach internal resources and exfiltrate reachable image-like responses via a trusted external service.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill documentation describes file access, shell execution, and networked publishing behavior, but it does not declare any permissions or capability boundaries. This is dangerous because users and orchestrators cannot accurately assess or constrain what the skill may access, especially since it handles local files, credentials, and remote publication to WeChat.

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding
The top-level description understates the full behavior of the skill by omitting operationally sensitive actions such as listing accounts, managing drafts, deleting drafts, uploading remote images, and directly publishing content. This mismatch is risky because operators may invoke the skill expecting simple article formatting/publishing while unknowingly granting access to broader account management and destructive or externally fetching actions.

Description-Behavior Mismatch

Medium
Confidence
83% confidence
Finding
The skill exposes draft listing and deletion capabilities beyond simple article extraction and publishing. In an agent setting, extra state-mutating operations widen the blast radius: a caller expecting only publish functionality could enumerate or delete unrelated drafts from the connected WeChat account.

Description-Behavior Mismatch

Medium
Confidence
84% confidence
Finding
The script supports uploading arbitrary local files or remote URLs to the WeChat material library independent of publishing a specific article. This broadens the skill from article publishing into general external file transfer, increasing the chance of unintended data exfiltration or misuse by an autonomous agent.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
Runtime package installation changes the environment dynamically and can execute untrusted package build/install logic. In a skill context, this undermines reproducibility and gives the tool an unexpected capability to modify the system and fetch code from package repositories.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly documents draft deletion capability without any warning, confirmation step, or safety guidance. In a content publishing context, deleting drafts is a destructive action that can cause data loss, accidental removal of unpublished work, or abuse if triggered by an untrusted prompt or mistaken operator input.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The draft deletion path performs an irreversible remote action immediately when `--delete-draft` is supplied, with no confirmation prompt, dry-run, or secondary safeguard. In an agent-driven workflow, accidental argument propagation or prompt injection into tool selection could cause unintended content loss.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
beautifulsoup4>=4.12.0
markdown>=3.5.0
pyyaml>=6.0.0
Confidence
94% confidence
Finding
The dependency is specified with a lower-bound range instead of an exact version, which makes builds non-reproducible and can allow unintended upgrades to vulnerable or incompatible releases. In a publishing skill that fetches web content and may process network responses, relying on floating dependency resolution increases supply-chain and stability risk.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
beautifulsoup4>=4.12.0
markdown>=3.5.0
pyyaml>=6.0.0
Pillow>=10.0.0
Confidence
93% confidence
Finding
Using an unpinned beautifulsoup4 version means future installations may resolve to different releases with changed behavior or newly introduced vulnerabilities. Because this skill extracts article content from web pages, parser behavior directly affects security and reliability when handling untrusted HTML.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
beautifulsoup4>=4.12.0
markdown>=3.5.0
pyyaml>=6.0.0
Pillow>=10.0.0
Confidence
93% confidence
Finding
The markdown package is not pinned, so installations can drift across versions and silently pull in vulnerable or breaking releases. Since the skill converts Markdown input into publishable content, dependency drift in this parser increases exposure to denial-of-service or parsing-related flaws.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
beautifulsoup4>=4.12.0
markdown>=3.5.0
pyyaml>=6.0.0
Pillow>=10.0.0
Confidence
96% confidence
Finding
An unpinned PyYAML dependency is riskier than many libraries because YAML parsers have a history of dangerous deserialization issues and API misuse. If the skill uses YAML for configuration, drifting to an unexpected version can reintroduce known flaws or compatibility changes that affect safe loading.

Unpinned Dependencies

Low
Category
Supply Chain
Content
beautifulsoup4>=4.12.0
markdown>=3.5.0
pyyaml>=6.0.0
Pillow>=10.0.0
Confidence
95% confidence
Finding
Pillow is unpinned, allowing arbitrary newer releases to be installed without review. Because the skill auto-generates cover images and may process untrusted image or text-derived inputs, dependency drift can expose the workflow to image parsing vulnerabilities or resource exhaustion issues.

Known Vulnerable Dependency: pyyaml — 8 advisory(ies): CVE-2019-20477 (Deserialization of Untrusted Data in PyYAML); CVE-2020-1747 (Improper Input Validation in PyYAML); CVE-2020-14343 (Improper Input Validation in PyYAML) +5 more

Critical
Category
Supply Chain
Confidence
91% confidence
Finding
PyYAML has a long history of unsafe deserialization vulnerabilities, and the requirement allows any version >=6.0.0 without proving that all allowed versions are safe for the intended usage. In a skill likely to consume YAML configuration, unsafe parsing of untrusted or attacker-controlled data could lead to code execution or serious compromise if insecure APIs are used.

Known Vulnerable Dependency: Pillow — 10 advisory(ies): CVE-2016-2533 (Pillow buffer overflow in ImagingPcdDecode); CVE-2023-50447 (Arbitrary Code Execution in Pillow); CVE-2021-27922 (Pillow Uncontrolled Resource Consumption) +7 more

Critical
Category
Supply Chain
Confidence
88% confidence
Finding
Pillow has numerous historically severe vulnerabilities, including memory corruption and resource exhaustion issues, and this skill explicitly generates cover images, making the library operationally relevant. If any untrusted images, fonts, or crafted content are processed, an exploitable Pillow issue could lead to denial of service and in some cases code execution or broader process compromise.

VirusTotal

67/67 vendors flagged this skill as clean.

View on VirusTotal

Static analysis

No suspicious patterns detected.