Back to skill

Security audit

Wechat Tutorial Editor Publisher

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly matches a WeChat tutorial publishing workflow, but it handles publishing credentials, personal contact data, uploads, and a writable local web server in ways that need careful review before use.

Review and modify this skill before installing. Do not store WeChat AppSecret in the skill directory or TOOLS.md; use a proper secret store or short-lived environment injection. Run the helper server only on loopback with authentication or a per-session token, add upload limits and file validation, remove the mandatory personal QR/contact footer unless explicitly approved for each article, and avoid the automatic global npm install path.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (6)

T01 · Skill Instruction Hijacking

Error
Location
patterns/article-pattern.md:85
Finding

Mandatory Promotional Footer and QR Code Hijack Generated Articles

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/publish-scripts/publish.sh:33
Finding

Insecure Persistent Handling of WeChat API Credentials

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/server.js:19
Finding

Unauthenticated Writable HTTP Service with Unrestricted CORS

Content
View full analysis
{ try { const { nickname, intro } = req.body; const infoContent = `Nickname: ${nickname}\nBiography: ${intro}\n`; await fs.writeFile(path.join(ASSETS_DIR, 'personal-info.txt'), infoContent, 'utf8'); res.json({ success: true, message: 'Personal information saved successfully' }); } catch (error) { console.error(error); res.status(500).json({ success: false, message: 'Save failed' }); } }); app.post('/api/save-steps', uploadSteps.fields([ { name: 'coverImage', maxCount: 1 }, { name: 'stepImages' } ]), async (req, res) => { // The handler writes uploaded images and steps.json under FILES_DIR. }); app.listen(PORT, () => { console.log(`Server started at http://localhost:${PORT}`); }); ``` ### Technical Analysis Both state-changing endpoints are exposed without authentication, authorization, CSRF protection, or a per-session capability token. Calling `cors()` without restrictions permits arbitrary web origins to issue cross-origin requests and read responses. The server calls `app.listen(PORT)` without specifying a loopback address. Node.js therefore listens on the unspecified network address under normal defaults, potentially exposing the service beyond the local browser if host firewall and network conditions allow it. The endpoints can overwrite persistent profile data and create or modify article-input directories. The interface is intended as a local editor, so there is no legitimate need for unrestricted network access. ### Attack Path 1. T ...[truncated 1073 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/server.js:44
Finding

Unbounded and Insufficiently Validated File Uploads

Content
View full analysis
{ cb(null, path.join(ASSETS_DIR, 'personal-imgs')); }, filename: (req, file, cb) => { cb(null, Date.now() + path.extname(file.originalname)); } }); const uploadPersonal = multer({ storage: personalStorage }); const stepsStorage = multer.diskStorage({ destination: (req, file, cb) => { const tempDir = path.join(FILES_DIR, 'temp_upload'); fs.ensureDirSync(tempDir); cb(null, tempDir); }, filename: (req, file, cb) => { cb(null, file.originalname); } }); const uploadSteps = multer({ storage: stepsStorage }); app.post('/api/save-steps', uploadSteps.fields([ { name: 'coverImage', maxCount: 1 }, { name: 'stepImages' } ]), async (req, res) => { // Uploaded files are moved from the shared temporary directory. }); ``` ### Technical Analysis Neither Multer instance defines limits for file size, total request size, number of parts, field size, or the number of `stepImages`. The server does not verify MIME type, extension, image signatures, or successful image decoding. Step images are initially saved using the client-controlled original filename in a shared `temp_upload` directory. Concurrent requests containing identical filenames can overwrite or interfere with one another. The handler subsequently empties the entire shared directory, which can delete another in-progress request's temporary files. The browser's `accept="image/*"` attribute is only a client-side hint and provides no server-side security. ### Attack Path 1. An attacker reaches the unauthenticated `/api/personal-info` or `/api/save-steps` endpoint. 2. The attacker submits very large files, many `stepImag ...[truncated 731 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/public/index.html:278
Finding

DOM-Based Script Injection Through Uploaded Filenames

Content
View full analysis
{ const previewItem = document.createElement('div'); previewItem.className = 'image-preview-item'; previewItem.innerHTML = ` ✕ `; previewContainer.appendChild(previewItem); }; ``` ### Technical Analysis The uploaded file's `file.name` value is interpolated directly into an HTML string and an inline JavaScript event handler. It is not HTML-encoded or JavaScript-string-encoded. A filename containing a single quote and JavaScript syntax can terminate the intended string and inject script into the `onclick` handler. The use of `innerHTML` makes the browser parse attacker-controlled content as markup. The image data URL is generated locally, but that does not sanitize the separately interpolated filename. ### Attack Path 1. An attacker creates an image file with a crafted filename containing quote characters and JavaScript syntax. 2. The victim selects or receives the file and adds it through the tutorial editor. 3. `handleImageUpload` reads the file and builds the preview with `innerHTML`. 4. The crafted filename alters the inline `onclick` handler. 5. When the injected event is triggered, JavaScript executes in the `http://localhost:3000` application origin. 6. The script can submit requests to the local API, modify form content, or replace stored author and tutorial data through the application's exposed endpoints. ### Impact Assessment Successful exploitation grants JavaScript execution in the local editor's origin. The injected script can perform all actions available to the page, including submitting profile or article data and manipulating the user interface. No authent ...[truncated 151 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/publish-scripts/publish.sh:17
Finding

Automatic Unpinned Global Installation of Publishing Dependency

Content
View full analysis
/dev/null 2>&1; then npm install -g @wenyan-md/cli if [ $? -eq 0 ]; then echo "wenyan-cli installed successfully" else echo "Installation failed. Run manually: npm install -g @wenyan-md/cli" exit 1 fi fi } ``` ### Technical Analysis When the command is absent, the script automatically installs the latest registry version of `@wenyan-md/cli` globally. No version is pinned, no lockfile controls this installation, and no package integrity or provenance is independently verified. An npm installation may execute package lifecycle scripts. Global installation also increases the blast radius by placing an executable in a shared command location. The resulting executable later receives the article and inherited WeChat credentials. The package name is not shown to be malicious in the reviewed project; the issue is the unsafe and mutable supply-chain installation process. ### Attack Path 1. The user runs `publish.sh` on a system without the `wenyan` command. 2. `check_wenyan` automatically requests the current registry version of `@wenyan-md/cli`. 3. npm downloads the package and dependencies and may execute installation lifecycle scripts. 4. The package is installed globally with the privileges of the current npm environment. 5. The installed command is then invoked with access to the article and exported WeChat credentials. 6. If a future registry release or transitive dependency is compromised, malicious code can execute during installation or publishing. ### Impact Assessment A compromised dependency could execute with the user's local privileges, access files available to that user, inherit publishing credenti ...[truncated 208 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (41)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The skill claims to write and publish tutorial content, but also directs collection and persistent storage of personal info, images, structured step data, and operation of a local web server. These additional data-handling and service-exposure behaviors increase privacy and attack-surface risks beyond what a simple editorial workflow implies.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill claims to write and publish tutorial content, but also directs collection and persistent storage of personal info, images, structured step data, and operation of a local web server. These additional data-handling and service-exposure behaviors increase privacy and attack-surface risks beyond what a simple editorial workflow implies.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill claims to write and publish tutorial content, but also directs collection and persistent storage of personal info, images, structured step data, and operation of a local web server. These additional data-handling and service-exposure behaviors increase privacy and attack-surface risks beyond what a simple editorial workflow implies.

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 36)May include surrounding context.

md
2. 启动服务器,打开[./scripts/public/index.html](http://localhost:3000/index.html)页面,用户将步骤数据填写到页面中并保存。

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The instructions tell the agent to store AppId and AppSecret locally without a user-facing security warning, normalization of risk, or safe storage requirements. Because these credentials can authorize WeChat API actions, insecure local storage materially increases the chance of account compromise and unauthorized publishing operations.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This is a direct instruction to collect, retain, and later reuse sensitive AppId/AppSecret credentials, creating persistent credential handling behavior in natural-language workflow instructions. The context makes it more dangerous because the skill is framed as content publishing, so users may not expect long-term credential retention or local secret management in the workspace.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: brace-expansion==5.0.4 — 5 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-45149 (brace-expansion: Large numeric range defeats documented `max` DoS protection) +2 more

High
Category
Supply Chain
Confidence
92% confidence
Finding

brace-expansion 5.0.4 is flagged for multiple denial-of-service issues involving pathological brace patterns that can trigger excessive CPU or memory consumption. Although this package is only present as a dev dependency path here, exploiting it can still affect developer or CI environments that process attacker-influenced glob patterns.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: multer==1.4.5-lts.2 — 11 advisory(ies): CVE-2025-47935 (Multer vulnerable to Denial of Service via memory leaks from unclosed streams); CVE-2025-47944 (Multer vulnerable to Denial of Service from maliciously crafted requests); CVE-2026-82333 (multer vulnerable to Denial of Service via oversized array index in field names) +8 more

High
Category
Supply Chain
Confidence
98% confidence
Finding

multer 1.4.5-lts.2 is explicitly deprecated in the lockfile with a note that Multer 1.x is affected by multiple vulnerabilities fixed in 2.x. Since this skill appears to include an Express stack and file upload handling, a vulnerable multipart parser is directly exposed to remote user input and can enable denial of service or other malformed-upload abuse.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: path-to-regexp==0.1.12 — 1 advisory(ies): CVE-2024-45296 (path-to-regexp vulnerable to Regular Expression Denial of Service via multiple r)

High
Category
Supply Chain
Confidence
93% confidence
Finding

path-to-regexp 0.1.12 is a long-lived Express dependency version associated with regular-expression denial-of-service risk in route matching. If route patterns are complex or attacker-controlled paths are repeatedly submitted, the service can spend excessive CPU time matching requests, degrading availability.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: picomatch==2.3.1 — 2 advisory(ies): CVE-2026-33672 (Picomatch: Method Injection in POSIX Character Classes causes incorrect Glob Mat); CVE-2026-33671 (Picomatch has a ReDoS vulnerability via extglob quantifiers)

High
Category
Supply Chain
Confidence
80% confidence
Finding

picomatch 2.3.1 is present only through development tooling in this lockfile and is flagged for glob-matching issues including ReDoS and incorrect matching behavior. That makes it a real dependency risk, but primarily to local development or CI workflows rather than the production attack surface of the skill itself.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: multer==1.4.5-lts.2 — 11 advisory(ies): CVE-2025-47935 (Multer vulnerable to Denial of Service via memory leaks from unclosed streams); CVE-2025-47944 (Multer vulnerable to Denial of Service from maliciously crafted requests); CVE-2026-82333 (multer vulnerable to Denial of Service via oversized array index in field names) +8 more

High
Category
Supply Chain
Confidence
97% confidence
Finding

The manifest includes multer 1.4.5-lts.1, and the static finding indicates the multer 1.x line has multiple known DoS-related advisories. In a server-side upload-handling component, a vulnerable multipart parser can let attackers send crafted requests that exhaust memory or otherwise disrupt service availability, which is especially relevant if this skill exposes a local or network-accessible step collector service.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The description requires producing tutorial-style WeChat articles in a specific Chinese publishing context and frames the skill around a fixed writing style, but it does not indicate that the user may choose another language or locale. This can be a natural-language policy issue when a skill implicitly forces a language without opt-in.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill directs collection and storage of personal profile information and images in local assets, which creates persistent handling of potentially sensitive personal data. In the context of a publishing workflow this may be functionally relevant, but absent minimization, consent, and retention controls it still presents unnecessary privacy and leakage risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill describes automatic conversion, image upload, and draft publishing to external services without a clear user-facing warning that article content and images will leave the local environment. This matters because users may provide unpublished content, proprietary screenshots, or personal images without understanding the external transmission.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation accesses a separate workspace file containing API credentials, which is a sensitive local source unrelated to ordinary article editing. Pulling secrets from a general workspace file creates unnecessary coupling and broadens the impact of compromise or accidental disclosure.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill tells the operator to store AppId/AppSecret locally for later reuse and to decrypt them later, introducing credential lifecycle management not justified by the stated purpose. Even if meant for convenience, local persistence of secrets increases the chance of credential theft, accidental disclosure, or reuse outside the user’s expectations.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The suggested trigger phrase "帮我发布这篇文章到微信公众号" is a natural, everyday request rather than a narrowly scoped command, and the document does not define stricter activation constraints or exclusion examples. In a markdown skill description, this can create ambiguity about when the skill should activate versus when the user is merely discussing publishing.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The step descriptions are written only in Chinese (e.g. installation and agent-creation instructions) with no indication that the skill supports other languages or that Chinese is required for a region-specific use case. This can violate language/locale policy when a skill implicitly forces one language without user opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The template explicitly instructs authors to publish a personal contact invitation alongside a personal WeChat QR code, which encourages disclosure of personally identifying contact information to a broad audience without any consent, privacy, or abuse-handling guidance. In the context of a one-click WeChat article publishing skill, this is more dangerous because the pattern can be repeatedly and automatically propagated into published content, increasing the risk of harassment, spam, scraping, and unintended personal exposure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This HTML/JavaScript code performs a POST request to /api/save-steps containing the cover image, step images, and step descriptions. Although the UI asks for confirmation to save, it does not disclose that local files and user-entered content will be transmitted to a server, which is a safety-relevant operation for code files under this rule.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The document declares lang="zh-CN" and all visible UI text is presented only in Simplified Chinese. This imposes a specific language on all users without any opt-in, alternative locale, or documented region-specific justification, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This page collects personal data, including a nickname, free-form profile text, and an uploaded image/WeChat QR code, even though the skill is described as a tutorial-writing and WeChat draft publishing tool. That creates an unjustified personal-information collection path and increases privacy, compliance, and misuse risk, especially because the data is submitted to a backend endpoint without any visible purpose limitation, consent notice, or retention details.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The requested profile text and QR code image are sensitive user-provided identifiers that are not clearly necessary for editing or publishing tutorial articles to a WeChat draft box. Collecting them without strong contextual justification can enable unnecessary profiling, social-contact harvesting, or later misuse of identity/contact artifacts.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script automatically installs a global npm package if wenyan is missing, which performs a networked system modification as a side effect before the user explicitly approves it. This creates supply-chain and environment-integrity risk, especially in automation or shared developer environments, because a publishing helper should not silently alter the host by fetching and executing code from npm.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script publishes content to the WeChat draft box immediately after basic checks, with no confirmation or dry-run step before the external action. In a content-generation skill, this increases the chance of unintended publication of wrong, unreviewed, or adversarially generated material to an external platform tied to real credentials.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.