other
- Location
lib/utils/markdown.js:591- Finding
Undisclosed Promotional Content Is Unconditionally Injected into Generated Articles
- Content
View full analysis
本文由稿定助手排版,- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
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.
lib/utils/markdown.js:591Undisclosed Promotional Content Is Unconditionally Injected into Generated Articles
lib/utils/markdown.js:178Markdown Links and Images Permit Unsafe URI Schemes
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.
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.
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.
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.
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.
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.
}
/** 列表项加粗:由 <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>`
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.
}
/** 列表项加粗:由 <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>`
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.
}
/** 列表项加粗:由 <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>`
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.
}
/** 列表项加粗:由 <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>`
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.
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.
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.
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.
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.
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.
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.
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.
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 }),
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.
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.
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.
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.
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.
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.
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.
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.
No suspicious patterns detected.