Back to skill

Security audit

内容工厂

Security checks across malware telemetry and agentic risk

Overview

This WeChat article skill is mostly purpose-related, but it also handles credentials and automatic publishing in ways users should review carefully before installing.

Install only if you intend to let this skill handle WeChat publishing. Before use, remove or rotate any real exposed credentials, avoid running commands that print API keys, restrict WECHAT_PROXY_URL to a trusted endpoint or disable it, review every file before upload, and require explicit approval before any WeChat draft or freepublish action.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (29)

Tainted flow: 'TOKEN_URL' from os.environ.get (line 96, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
}

        try:
            response = requests.get(TOKEN_URL, params=params, headers=self._proxy_headers, timeout=10)
            response.raise_for_status()
            data = response.json()
Confidence
98% confidence
Finding
response = requests.get(TOKEN_URL, params=params, headers=self._proxy_headers, timeout=10)

Tainted flow: 'url' from os.environ.get (line 552, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
json_data = json.dumps(payload, ensure_ascii=False).encode('utf-8')
            headers = {'Content-Type': 'application/json; charset=utf-8'}
            headers.update(self._proxy_headers)
            response = requests.post(url, data=json_data, headers=headers, timeout=30)
            response.raise_for_status()
            data = response.json()
Confidence
97% confidence
Finding
response = requests.post(url, data=json_data, headers=headers, timeout=30)

Tainted flow: 'url' from os.environ.get (line 552, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
}

        try:
            response = requests.post(url, json=payload, headers=self._proxy_headers, timeout=30)
            response.raise_for_status()
            data = response.json()
Confidence
96% confidence
Finding
response = requests.post(url, json=payload, headers=self._proxy_headers, timeout=30)

Tainted flow: 'url' from os.environ.get (line 552, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
try:
            with open(image_path, 'rb') as f:
                files = {'media': (image_path.name, f, 'image/png')}
                response = requests.post(url, files=files, headers=self._proxy_headers, timeout=60)
                response.raise_for_status()
                data = response.json()
Confidence
97% confidence
Finding
response = requests.post(url, files=files, headers=self._proxy_headers, timeout=60)

Tainted flow: 'url' from os.environ.get (line 552, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
try:
            with open(image_path, 'rb') as f:
                files = {'media': (image_path.name, f, 'image/png')}
                response = requests.post(url, files=files, headers=self._proxy_headers, timeout=60)
                response.raise_for_status()
                data = response.json()
Confidence
97% confidence
Finding
response = requests.post(url, files=files, headers=self._proxy_headers, timeout=60)

Lp3

Medium
Category
MCP Least Privilege
Confidence
97% confidence
Finding
The skill invokes shell commands, reads local files and credentials, writes files, and uses networked APIs, yet it declares no permissions or user-facing disclosure of these capabilities. This creates a dangerous trust gap: an operator may believe the skill only writes content while it can access secrets, persist data, and transmit content externally.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The manifest says the skill researches and generates Markdown/HTML articles, but the body also performs credential checks, image generation/compression, and automatic WeChat publishing. This mismatch can cause users or orchestration systems to authorize a much broader capability set than they intended, leading to unintended external publication and secret handling.

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The document includes real-looking secrets inline in a configuration example despite explicitly warning against hardcoding and committing credentials. Even in documentation, publishing plausible live credentials can cause accidental reuse, confusion about whether they are active, and actual secret exposure if they were copied from a real environment.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The deprecated `wechat_config.py` example hardcodes an AppID and AppSecret directly in source, contradicting the later security guidance. This normalizes insecure practice and may expose actual credentials if the values are real or copied from a production setup.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The documented workflow expands beyond article generation into credential validation and automatic WeChat publishing, which are materially different operations with security consequences. Hidden operational scope increases the chance of unauthorized publication, accidental secret exposure, and unsafe automation in environments that expected a writing-only skill.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The skill reads API keys directly from fixed credential file paths to test service availability, which exceeds what a content-writing skill should need. Local credential extraction increases the blast radius of compromise and normalizes secret access without clear necessity or consent.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
Automatic publication to a WeChat Official Account is a privileged external action unrelated to merely generating article drafts. If triggered unexpectedly, it can publish unreviewed or sensitive content under the user's brand/account, creating reputational, compliance, and data-leak risks.

Intent-Code Divergence

Medium
Confidence
90% confidence
Finding
Unresolved merge-conflict markers leave contradictory operational instructions in place, including topic restrictions and freshness requirements. In agentic workflows, ambiguous or conflicting instructions can lead to unpredictable execution paths, bypassed safeguards, or accidental invocation of the wrong behavior.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
This script goes beyond article/content generation and performs live publishing-side operations against the WeChat API, including uploading media and generating deployment configuration. In the context of a content-generation skill, that expanded capability increases risk because it can act on external accounts and persist publishing credentials/artifacts without a clear separation of duties or user approval.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The file contains hardcoded WeChat APPID and APPSECRET directly in source code. Embedded credentials are easily leaked through source control, logs, package distribution, or reuse by unauthorized parties, enabling account/API abuse.

Context-Inappropriate Capability

Medium
Confidence
97% confidence
Finding
The script writes a Python configuration file containing the media ID plus APPID and APPSECRET, creating another plaintext secret store on disk. This expands the exposure surface for credentials and mixes publishing/deployment state into a generated module that may later be imported, committed, or distributed.

Description-Behavior Mismatch

Medium
Confidence
90% confidence
Finding
The script adds remote WeChat publishing capability, which is broader than the stated article-generation workflow. In a skill ecosystem, undocumented execution capabilities are dangerous because users may grant trust for content generation but not expect credential use, network publication, or account-side effects.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The code loads WeChat credentials from .env/environment and uses them for remote publishing, a privileged capability not justified by a content-creation-only description. This mismatch increases the chance of secret misuse and covert external actions under the guise of benign article generation.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The documentation shows credential examples in realistic secret formats and even demonstrates partially revealed values in expected output. In a skill that handles API keys and publishing credentials, this increases the risk of users echoing secrets into terminals, logs, screenshots, or copied examples.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill requires writing full research context and all source URLs into shared memory for later retrieval, but does not clearly warn the user that their research artifacts will be retained across sessions. Cross-session persistence increases exposure of user-provided topics, source selections, and derived content to other workflows or later operators.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill mandates saving multiple local output files without a prominent upfront warning that user content will be written to disk in several formats. Silent persistence creates privacy and data-handling risks, especially when content may contain proprietary topics, drafts, or unpublished messaging.

Missing User Warnings

High
Confidence
99% confidence
Finding
The workflow includes automatic external publication using account credentials, but that behavior is not clearly disclosed in the high-level description. Users may provide sensitive draft content believing it will remain local, only for it to be transmitted to a third-party platform under their account.

Missing User Warnings

Medium
Confidence
83% confidence
Finding
The guide instructs use of external image-generation APIs based on article title and theme, but provides no warning that user content will be transmitted to third-party services. In a content-authoring skill, titles/themes may contain unpublished campaign material, sensitive business plans, or personal data, so silent external sharing creates a meaningful privacy and data-governance risk.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script prints loaded secret values to stdout, only partially masked and sometimes fully shown when short. This can expose API keys or app secrets in terminal logs, CI output, shell history capture, screenshots, or remote execution logs, leading to credential leakage.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The script silently overwrites a local Python config file with credentials and media metadata, without explicit warning or confirmation. This can lead to accidental secret persistence, unintended file replacement, and later leakage if the file is checked into source control or shared.

VirusTotal

65/65 vendors flagged this skill as clean.

View on VirusTotal

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
API_KEY_SETUP.md:55

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
CONFIGURATION.md:100

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/create_default_cover.py:238

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/generate_cover_photo.py:433