Back to skill

Security audit

WeChat Article Archive

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but its image downloader can fetch arbitrary embedded resource URLs into the archive without host, scheme, size, or network-safety limits.

Review before installing or running on untrusted saved HTML. Use it only with WeChat URLs and output folders you choose, consider --skip-images for untrusted content, and prefer running it in a sandboxed environment without access to internal networks or sensitive local files until asset URL and size limits are added.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/archive_wechat_article.py:322
Finding

Unrestricted article asset retrieval permits SSRF and non-HTTP resource access

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/archive_wechat_article.py:322
Finding

Unbounded image response buffering permits memory and disk exhaustion

Content
View full analysis
Remediation
View remediation
max_bytes: raise ValueError("image exceeds maximum size") output.write(chunk) ``` 4. Download into a temporary file and atomically rename it only after all validation succeeds. Delete partial files on failure. 5. Enforce a maximum number of images per article and a cumulative archive-size budget. 6. Require an approved image `Content-Type` and validate file signatures rather than trusting extensions or response headers. 7. Add connection, read, and total-operation deadlines. 8. Apply OS-level memory, disk, and network quotas when the skill runs in an automated agent environment. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Python dependency uses an open-ended version range

Content
View full analysis
=4.12 ``` ### Technical Analysis The requirement specifies only a minimum version. Every fresh installation can therefore resolve to a different future Beautiful Soup release and different transitive dependencies. No evidence was found that the currently referenced package is malicious. The issue is that reviewed source code does not uniquely determine the code installed and executed during future setup. A compromised, malicious, or incompatible future release satisfying `>=4.12` could be installed automatically. The npm dependencies have a lockfile containing registry URLs and integrity hashes, but the Python dependency has no equivalent fully pinned, hash-verified lock file. ### Attack Path 1. A user follows the documented setup command: ```bash .venv/bin/python -m pip install -r requirements.txt ``` 2. Pip queries the configured package index and selects the newest release satisfying `beautifulsoup4>=4.12`. 3. If a future compatible release or dependency is compromised, pip downloads and installs it. 4. The dependency executes in the Python process when the archive script imports and uses Beautiful Soup. 5. Any malicious package behavior would inherit the invoking user's process privileges. This is a supply-chain hardening weakness rather than evidence of a currently malicious dependency. ### Impact Assessment A compromised dependency could theoretically access files, environment variables, network resources, and output locations available to the skill process. More commonly, open-ended resolution can cause unexpected compatibility or parsing changes that make installations non-reproducible. The immediate risk is low because the package name is legitimate, it comes from the normal Python ecosystem, and no known ma ...[truncated 54 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared purpose is a local archival/export tool that saves WeChat articles and image-note pages as Markdown plus local assets in a user-specified folder. This code chunk instead implements an extractor/parser: it accepts a URL or HTML, fetches supported pages over the network, parses the DOM and embedded JS, identifies content type, extracts metadata/content/publish time/images, and optionally extracts links/tags/repost metadata. While this could be a supporting component of a larger archival tool, on its own it does not carry out the core declared behaviors of writing files locally, choosing a destination folder, converting to Markdown, or downloading assets. It also includes undeclared capabilities such as accessing weixin.sogou.com, following redirects/transfer links, and optional extraction of mp links/tags/repost metadata. Therefore the supplied code does not accurately match the declared description.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- Parses the article with the bundled `extract.js`.

Known Vulnerable Dependency: undici==7.28.0 — 5 advisory(ies): CVE-2026-13697 (undici vulnerable to cross-user information disclosure and parse-time crash via ); CVE-2026-16728 (undici vulnerable to downstream response desynchronization via retry interceptor); CVE-2026-14643 (undici vulnerable to cross-user information disclosure via whitespace around equ) +2 more

High
Category
Supply Chain
Confidence
95% confidence
Finding

The lockfile includes undici 7.28.0, and the advisory set describes request/response parsing and desynchronization flaws that can lead to cross-user information disclosure or crashes. In this skill's context, the package is especially relevant because the tool fetches remote WeChat content and processes untrusted network responses, making HTTP client parsing flaws materially more dangerous than a dormant dependency issue.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

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

python
process.exit(1);
}});
"""
    env = os.environ.copy()
    if html_file:
        env["WECHAT_HTML_FILE"] = str(html_file)
    res = subprocess.run(

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill instructs the agent to run a local Python script, access environment variables, write files, and fetch remote content, but it declares no explicit tool scope or permissions. This creates an authorization gap where an orchestrator or reviewer cannot easily constrain or audit the skill's shell, network, and filesystem behavior, increasing the chance of overbroad execution.

Content

No source excerpt is available for this finding.

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

python
env = os.environ.copy()
    if html_file:
        env["WECHAT_HTML_FILE"] = str(html_file)
    res = subprocess.run(
        [node, "-e", js],
        capture_output=True,
        text=True,

Tainted flow: 'node' from os.environ.get (line 28, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
95% confidence
Finding

The executable path comes from os.environ.get("NODE"), then is passed directly to subprocess.run. In an agent/tooling environment, a caller or surrounding runtime that can influence environment variables could replace NODE with an attacker-controlled binary, causing arbitrary code execution under the agent's privileges.

Content

Scanner excerpt · scripts/archive_wechat_article.py (reported line 54)May include surrounding context.

python
env = os.environ.copy()
    if html_file:
        env["WECHAT_HTML_FILE"] = str(html_file)
    res = subprocess.run(
        [node, "-e", js],
        capture_output=True,
        text=True,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This code file contains only Chinese-language user-facing error strings, which forces a specific language on users. Under the policy, locale or language constraints should either be user-selectable or clearly documented as intentionally region-specific.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code performs an HTTP request to a user-provided WeChat URL and sends request metadata including a user-agent and Accept-Language header. There is no confirmation prompt, logging, or comment/docstring here warning that external network access will occur, which fits the missing user warning criterion for code files.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: qs==6.15.3 — 2 advisory(ies): CVE-2026-82417 (qs: Denial of Service via Attacker Controlled isBuffer); CVE-2026-82562 (qs array-limit bypass via bracket-key comma parsing)

Low
Category
Supply Chain
Confidence
89% confidence
Finding

The lockfile pins qs to 6.15.3, and the supplied advisory metadata indicates known denial-of-service and parser-bypass issues in that version. Even though package-lock.json itself is not executable, including a vulnerable dependency is a real supply-chain weakness if the application uses qs on attacker-controlled query strings or form data.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 3)May include surrounding context.

json
{
  "dependencies": {
    "cheerio": "^1.2.0",
    "dayjs": "^1.11.19",
    "lodash.unescape": "^4.0.1",
    "qs": "^6.15.0"

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 4)May include surrounding context.

json
{
  "dependencies": {
    "cheerio": "^1.2.0",
    "dayjs": "^1.11.19",
    "lodash.unescape": "^4.0.1",
    "qs": "^6.15.0"
  }

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 5)May include surrounding context.

json
"dependencies": {
    "cheerio": "^1.2.0",
    "dayjs": "^1.11.19",
    "lodash.unescape": "^4.0.1",
    "qs": "^6.15.0"
  }
}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 6)May include surrounding context.

json
"cheerio": "^1.2.0",
    "dayjs": "^1.11.19",
    "lodash.unescape": "^4.0.1",
    "qs": "^6.15.0"
  }
}

Known Vulnerable Dependency: qs==6.15.3 — 2 advisory(ies): CVE-2026-82417 (qs: Denial of Service via Attacker Controlled isBuffer); CVE-2026-82562 (qs array-limit bypass via bracket-key comma parsing)

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The manifest resolves to a known vulnerable qs version with published advisories, including denial-of-service and parser limit bypass issues. In the context of a skill that archives WeChat articles and may process attacker-influenced URLs, query strings, or imported HTML-derived parameters, malformed input could trigger excessive resource consumption or bypass expected parsing constraints if qs is used on untrusted data.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
50% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
beautifulsoup4>=4.12

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The request hard-codes an Accept-Language header of 'zh-CN,zh;q=0.9,en;q=0.8', which imposes a locale/language preference rather than letting the user choose. This is a natural-language policy concern because it forces a specific language/locale in behavior without documented opt-in or justification.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.