Back to skill

Security audit

公众号文章排版

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly performs Markdown-to-WeChat preview generation as described, but it uploads full article HTML and silently inserts promotional WeChat mini-program content into generated articles.

Review before installing. Do not use this skill on confidential drafts unless you are comfortable uploading the full rendered HTML to edit.shiker.tech, and inspect generated HTML before publication because it currently adds an undisclosed branded mini-program header to every article. For untrusted Markdown, be aware that unsafe link or image URI schemes may pass through into the generated HTML.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

other

Warning
Location
lib/utils/markdown.js:591
Finding

Undisclosed Promotional Content Is Unconditionally Injected into Generated Articles

Content
View full analysis
本文由稿定助手排版,
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
lib/utils/markdown.js:178
Finding

Markdown Links and Images Permit Unsafe URI Schemes

Content
View full analysis
{ const key = (id || text || '').toLowerCase().replace(/\s+/g, ' ') const r = refs[key] if (!r) return _ const url = escapeHtml(r.url) const t = escapeHtml(text || r.url) const titleAttr = r.title ? ` title="${escapeHtml(r.title)}"` : '' return `${t}` }) .replace(/\[([^\]]*)\]\(([^)]+)\)/g, (_, text, hrefPart) => { const parts = hrefPart.trim().split(/\s+/) const href = (parts[0] || '').trim() const title = parts[1] ? parts[1].replace(/^["']|["']$/g, '') : '' const url = escapeHtml(href) const t = escapeHtml(text || url) const titleAttr = title ? ` title="${escapeHtml(title)}"` : '' return `${t}` }) ``` Related image rendering paths at `lib/utils/markdown.js:157-174`, `230-250`, and `546-551` similarly escape attribute characters but do not validate URI schemes before placing destinations into `src`. ### Technical Analysis HTML escaping prevents attribute-boundary injection, but it does not make a URI safe. A destination such as `javascript:...`, `data:...`, or another active or unexpected scheme remains semantically active after `escapeHtml()` and is inserted directly into an `href` or `src` attribute. For example, untrusted Markdown can provide a link destination using an active scheme. If the generated preview or downstream publishing environment does not sanitize that scheme, activation of the link may execute script in the preview page's bro ...[truncated 1878 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (25)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The README title and instructions are written in Chinese, and the workflow guidance is presented only in Chinese with no indication that other languages are supported. Under the policy, forcing a specific language without user opt-in can be a natural-language policy violation unless the locale constraint is explicitly justified.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README says the skill activates when user input contains listed keywords, then adds a free-form example phrase ('用预设主题把这篇 md 排成公众号并生成复制链接') without negative examples or clear exclusion conditions. Terms like '主题预览' and '公众号主题排版' are broad enough to overlap with ordinary discussion about article formatting, making activation scope ambiguous.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill declares tools (filesystem, http, shell) but does not define an explicit permission scope such as allowed tools, destinations, or environment restrictions, while the workflow clearly performs network access to an external domain and shell execution. This weakens containment and makes it easier for an agent runtime to grant broader-than-necessary capabilities, increasing the blast radius if the skill is modified, misused, or combined with untrusted input.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill instructs sending the rendered article HTML to https://edit.shiker.tech/api/copy, which means user content is transmitted to a third-party service, but it does not prominently warn users about this data transfer before execution. If users provide unpublished, sensitive, or proprietary content, the skill could exfiltrate that material outside the local environment without informed consent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This JavaScript file contains user-facing natural-language content such as theme names, descriptions, shortcode labels, and comments that are predominantly Chinese, indicating the skill experience is effectively localized to a specific language by default. Under the stated policy, forcing a specific language without offering user choice or documenting a justified locale constraint is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · lib/utils/markdown.js (reported line 100)May include surrounding context.

js
}

  /** 列表项加粗:由 <strong>标签</strong>:说明 改为 <strong><span leaf="">标签<span textstyle="" style="font-weight: normal">说明</span></span></strong> */
  function wrapListItemStrong(html) {
    const m = html.match(/^<strong style="([^"]*)">([\s\S]*?)<\/strong>([\s\S]*)$/)
    if (!m) return html
    return `<strong style="${m[1]}"><span leaf="">${m[2]}<span textstyle="" style="font-weight: normal">${m[3]}</span></span></strong>`

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · lib/utils/markdown.js (reported line 113)May include surrounding context.

js
}

  /** 列表项加粗:由 <strong>标签</strong>:说明 改为 <strong><span leaf="">标签<span textstyle="" style="font-weight: normal">说明</span></span></strong> */
  function wrapListItemStrong(html) {
    const m = html.match(/^<strong style="([^"]*)">([\s\S]*?)<\/strong>([\s\S]*)$/)
    if (!m) return html
    return `<strong style="${m[1]}"><span leaf="">${m[2]}<span textstyle="" style="font-weight: normal">${m[3]}</span></span></strong>`

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · lib/utils/markdown.js (reported line 115)May include surrounding context.

js
}

  /** 列表项加粗:由 <strong>标签</strong>:说明 改为 <strong><span leaf="">标签<span textstyle="" style="font-weight: normal">说明</span></span></strong> */
  function wrapListItemStrong(html) {
    const m = html.match(/^<strong style="([^"]*)">([\s\S]*?)<\/strong>([\s\S]*)$/)
    if (!m) return html
    return `<strong style="${m[1]}"><span leaf="">${m[2]}<span textstyle="" style="font-weight: normal">${m[3]}</span></span></strong>`

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · lib/utils/markdown.js (reported line 481)May include surrounding context.

js
}

  /** 列表项加粗:由 <strong>标签</strong>:说明 改为 <strong><span leaf="">标签<span textstyle="" style="font-weight: normal">说明</span></span></strong> */
  function wrapListItemStrong(html) {
    const m = html.match(/^<strong style="([^"]*)">([\s\S]*?)<\/strong>([\s\S]*)$/)
    if (!m) return html
    return `<strong style="${m[1]}"><span leaf="">${m[2]}<span textstyle="" style="font-weight: normal">${m[3]}</span></span></strong>`

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code emits fixed Chinese labels in user-visible output such as aria-label text for task items ('已完成' / '未完成'). The file provides no apparent language selection or opt-in, which violates the language/locale policy for natural-language content.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

When a gallery has no items or no explicit title, the renderer outputs Chinese-only fallback text ('暂无图片', '滑动图床'). Because this natural-language output is unconditional, it enforces a specific locale rather than respecting user choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The alert label mapping converts alert types to Chinese-only text ('建议', '提醒', '重要', '警告', '注意') for rendered output. There is no mechanism here for locale negotiation, fallback, or user opt-in.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The renderer unconditionally injects a promotional article header into all generated output, which changes user content and adds undisclosed third-party/product messaging. In a rendering utility, silently modifying output beyond requested formatting is a supply-chain trust issue because downstream publishers may unknowingly distribute unwanted content.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code embeds fixed mini-program promotional links and app identifiers into rendered articles without user consent. This creates hidden outbound/app-deep-link behavior in generated content, which can mislead end users, violate publisher expectations, and act as unauthorized traffic or attribution injection.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The exported full HTML always includes ARTICLE_HEADER_HTML containing Chinese promotional text for '稿定助手'. This forces Chinese-language output regardless of user preference and offers no opt-in or locale-aware alternative.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This JavaScript file defines user-facing preset names entirely in Chinese and documents support as '中文或英文 key', but no actual English aliases are present in the PRESETS object. That creates a locale-specific UX constraint without user opt-in or a clearly documented region-specific justification.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
97% confidence
Finding

This code transmits generated HTML to an external domain, which is expected for producing a hosted preview link but still represents a real data exposure boundary. In the context of a publishing helper skill, the transmission is contextualized, yet it remains dangerous because the content may include confidential draft material and the code does not provide safeguards, minimization, or explicit consent.

Content

Scanner excerpt · wechat-copy.js (reported line 30)May include surrounding context.

js
const html = getFullHtml(content, opts.themeId, opts.imageStyleId, opts.layoutId, null, opts.codeThemeId)

const res = await fetch('https://edit.shiker.tech/api/copy', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ html }),

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script uploads rendered HTML derived from the local Markdown to a third-party remote API without a prominent user-facing warning or consent step. If the Markdown contains unpublished articles, internal links, tracking tokens, or sensitive embedded data, this causes silent exfiltration to an external service outside the user's environment.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script performs additional local side effects not clearly disclosed by the skill description: it writes a full rendered HTML file and a preview URL file next to the input Markdown. This can unexpectedly persist potentially sensitive transformed content on disk, violating user expectations and increasing the chance of accidental exposure through later commits, sync, or sharing.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code file contains natural-language instructions and interface text exclusively in Chinese, including usage/help text and error messaging. Under the language/locale policy, forcing a specific language without offering user choice or documenting a justified locale constraint is a policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This JavaScript file includes its descriptive comments entirely in Chinese, stating functionality and supported languages without any indication that language is configurable or intentionally limited to a region-specific audience. Under the policy rule for natural-language violations, forcing a specific language without user opt-in can be considered a locale policy issue.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The header comment says the priority is CLI > preset > environment variables > defaults, but the implementation resolves theme/layout/image/code options as CLI > environment variables > preset > defaults. This is an active contradiction in the file's own documentation about how user-supplied configuration is applied.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The implementation writes a full rendered HTML artifact to disk as a side effect that is not fully reflected in the user-facing description. While not inherently malicious, hidden persistence of rendered content can surprise users and create minor confidentiality and hygiene risks if the HTML contains sensitive article material or embedded data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The script emits a user-facing stderr message only in Chinese when input is missing. This reinforces a forced language choice in the CLI experience without user opt-in or documented justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The catch block writes a Chinese-prefixed error message to stderr, again imposing a single language on all users. Because no language selection or region-specific justification is present, this conflicts with the stated language/locale policy.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.