Back to skill

Security audit

微信公众号发布助手

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its WeChat article workflow, but it needs review because it can act on a live WeChat account, persists access tokens locally, and includes unsafe command/evaluation patterns.

Install only if you intend to let this skill work with a real WeChat Official Account. Use a dedicated workspace, store secrets in keyring rather than config files, delete token caches after use, run dry-run first, require human confirmation before live draft or publish actions, and avoid running the screenshot or extractor helpers on untrusted paths or HTML until they are hardened.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
Findings (33)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# Open in browser
    open_cmd = f'browser open --url "{file_url}"'
    result = subprocess.run(open_cmd, shell=True, capture_output=True, text=True)
    
    if result.returncode != 0:
        print(f"❌ Failed to open browser: {result.stderr}")
Confidence
97% confidence
Finding
This command is built with attacker-influenced input (`html_path` via `file_url`) and executed with `shell=True`, which enables shell metacharacter injection if the path contains characters such as quotes or command separators. In this skill context, the script is explicitly designed to open local files in a browser tool, so untrusted path input can lead to arbitrary command execution under the agent's privileges.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if args.install:
        import subprocess
        subprocess.check_call([
            sys.executable, "-m", "pip", "install",
            "-r", str(Path(__file__).resolve().parent / "requirements.txt")
        ])
Confidence
94% confidence
Finding
The script exposes a self-install mode that invokes pip through subprocess, which can modify the local Python environment and execute package installation logic from dependencies. In an agent/skill context, this is risky because a caller may trigger environment mutation unexpectedly, and installation side effects can include arbitrary code execution from setup hooks or compromised packages.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
Embedding package installation in an article publisher broadens the script's capabilities beyond its stated purpose and allows environment changes on demand. In a skill setting, unexpected self-install behavior increases supply-chain and execution risk because dependency installation can run untrusted package code and alter the host used by other tasks.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill prominently advertises one-click WeChat publishing and draft-box interaction but does not warn users that running the publishing stage can modify a live account state or trigger downstream distribution workflows. In an automation context, lack of explicit safety gating increases the risk of unintended publication, account misuse, or operational mistakes with real audience impact.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The credential setup section instructs users to store a WeChat App ID and App Secret in keyring or environment variables without prominently warning that these are sensitive secrets. This can normalize unsafe handling, encourage copy-paste into insecure contexts, and increase the chance of credential leakage or reuse in logs, shell history, or shared environments.

Vague Triggers

Medium
Confidence
86% confidence
Finding
The default prompt is broadly phrased and can activate this publishing skill for generic requests to publish Markdown files or URLs, without clearly constraining target account, confirmation requirements, or content source trust. Because the action publishes to a WeChat Official Account draft, over-broad invocation increases the chance of unintended triggering and accidental content publication in response to ambiguous user requests.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This rule forces the agent to impersonate a specific human ('老板') and explicitly suppress disclosure that the speaker is an AI or agent. That creates a deceptive output policy and can mislead users about authorship, accountability, and provenance, especially when responses are presented as first-person human statements without user consent.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The document recommends a credential lookup order that falls back from the OS keyring to an environment variable and then to config.json, but it does not warn that env vars and config files are often exposed through shell history, process inspection, backups, source control, or local file disclosure. In a deployment guide, this can normalize weaker secret storage and increase the chance that a WeChat app secret is stored in plaintext.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The document instructs users to run a real publication step that uploads content into a WeChat draft box, but it does not warn that this action affects an external account and may use live credentials. In an agent-skill context, omission of an explicit confirmation or safety gate can cause unintended publication actions, misuse of privileged tokens, or content being pushed to the wrong account.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The document explicitly records that a real access token is stored in `skills/wechat-article-publisher/.token_cache.json` and only warns to delete it before publication. Even though this is operational guidance rather than code, normalizing storage of live bearer tokens in a workspace file creates a realistic risk of accidental disclosure through commits, packaging, logs, backups, or shared environments.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The README states that Claude will automatically trigger this skill whenever a user provides a WeChat article link, but it does not describe meaningful constraints, confirmation requirements, or trust boundaries. In an agent setting, overly broad auto-trigger conditions can cause unintended network requests to attacker-supplied URLs or unexpected processing of untrusted content, increasing the attack surface and creating opportunities for prompt-routing abuse or surprise data handling.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The script can mutate the Python environment by running pip without presenting a meaningful safety warning or obtaining clear confirmation. This is dangerous in shared or automated execution contexts because users may invoke the skill expecting publishing only, while it instead installs software and may trigger package code execution.

Unvalidated Output Injection

High
Category
Output Handling
Content
# Open in browser
    open_cmd = f'browser open --url "{file_url}"'
    result = subprocess.run(open_cmd, shell=True, capture_output=True, text=True)
    
    if result.returncode != 0:
        print(f"❌ Failed to open browser: {result.stderr}")
Confidence
96% confidence
Finding
The script forwards unvalidated user-controlled data into a shell command that drives a privileged browser tool. Because the URL is embedded inside a shell command string, a crafted filename can break quoting and inject additional commands, turning a screenshot helper into a command-execution vector.

Credential Access

High
Category
Privilege Escalation
Content
## 凭据存储

**位置:** Windows Credential Manager(keyring)
- service: `wechat-article-publisher`
- username: `<your-app-id>`
Confidence
90% confidence
Finding
The document provides concrete instructions for storing a WeChat app secret in Windows Credential Manager via keyring. While this is better than hardcoding secrets in the repo, it still documents handling of production credentials in an agent skill reference and may encourage broad local access patterns, accidental disclosure, or reuse without least-privilege controls. In this skill context, the presence of API publishing, IP allowlisting, and operational guidance makes the credential materially sensitive.

Credential Access

High
Category
Privilege Escalation
Content
print(f"  [SECRET] 来源: 环境变量 {ENV_APP_SECRET}(CI/临时)")
        return env_val
    if config_fallback and not config_fallback.startswith("USE_"):
        print(f"  [SECRET] 来源: config.json(本地开发,请尽快迁移到 keyring)")
        return config_fallback
    raise RuntimeError(
        f"AppSecret 未找到:请用 keyring 存储(service='{KEYRING_SERVICE}', username='<app_id>')、"
Confidence
84% confidence
Finding
Allowing a plaintext AppSecret fallback from config.json creates an avoidable secret-at-rest exposure risk if the config file is committed, copied, or read by other local users or tools. In a reusable skill context, encouraging plaintext credential storage is more dangerous because artifacts are often shared and automated.

Unpinned Dependencies

Low
Category
Supply Chain
Content
if [ -f "package.json" ]; then
  npm install
  echo "[OK] Node 依赖 OK"
else
  echo "[X] 未找到 scripts/extractor/package.json"
  exit 1
fi
Confidence
97% confidence
Finding
The script runs 'npm install' without enforcing a locked dependency graph via 'npm ci' or validating a lockfile. This can pull newer transitive packages than expected, increasing supply-chain risk and reducing build reproducibility, especially because the script automatically installs code from the network and then runs related local checks.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
beautifulsoup4>=4.12.0
markdown>=3.5.0
pyyaml>=6.0.0
Confidence
95% confidence
Finding
The dependency is specified with a lower-bound constraint only, which allows future installs to resolve to different versions over time. This weakens build reproducibility and can unintentionally introduce vulnerable or incompatible releases through the supply chain.

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
95% confidence
Finding
Using an unpinned version range for beautifulsoup4 means installations are not deterministic and may pull in newer versions with unexpected behavior or newly introduced issues. In a publishing-related skill, parser libraries are often exposed to external content, so supply-chain drift is undesirable.

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
The markdown package is not pinned, so dependency resolution may change across environments or over time. This increases supply-chain risk and makes it easier for vulnerable versions to be introduced unintentionally.

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
95% confidence
Finding
A lower-bound-only constraint for pyyaml permits non-reproducible builds and can result in installation of versions that have not been validated by the project. For a tool that may process structured content, dependency consistency matters for security and stability.

Unpinned Dependencies

Low
Category
Supply Chain
Content
beautifulsoup4>=4.12.0
markdown>=3.5.0
pyyaml>=6.0.0
Pillow>=10.0.0
Confidence
97% confidence
Finding
Pillow is specified with only a minimum version, allowing installations to vary and increasing exposure to supply-chain drift. Because image-processing libraries routinely parse complex untrusted file formats and Pillow has a history of severe memory-safety issues, unpinned resolution is more dangerous here than for purely utility libraries.

Known Vulnerable Dependency: markdown — 2 advisory(ies): CVE-2025-69534 (Python-Markdown has an Uncaught Exception); CVE-2025-69534 (Python-Markdown version 3.8 contain a vulnerability where malformed HTML-like se)

High
Category
Supply Chain
Confidence
94% confidence
Finding
The script installs 'markdown' without pinning to a known-safe version, and the scanner reports known advisories affecting some versions. Because this installer fetches the latest available package at runtime, users may receive a vulnerable release depending on repository state, making downstream processing of untrusted content riskier.

Known Vulnerable Dependency: requests — 10 advisory(ies): CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +7 more

High
Category
Supply Chain
Confidence
95% confidence
Finding
The installer pulls 'requests' without a constrained safe version even though the package has had multiple security advisories, including credential leakage scenarios under certain usage patterns. In the context of a content-publishing suite that likely performs network requests, an unsafe requests version could expose authentication material or weaken transport behavior in downstream scripts.

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
96% confidence
Finding
The script installs 'Pillow' unpinned despite a history of serious vulnerabilities, including issues triggered by crafted image files. Given this skill includes image-generation functionality, the contextual risk is higher because image parsing or manipulation may process attacker-controlled content and could lead to denial of service or worse if an affected version is used.

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
96% confidence
Finding
The installer includes unpinned 'pyyaml', a package with well-known unsafe deserialization history when used incorrectly or in older versions. If any downstream component loads YAML from untrusted or semi-trusted sources, an affected version or unsafe loader choice could enable code execution or other serious compromise.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/extractor/extract.js:206