Back to skill

Security audit

hekouwang-yandu-deck-skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent deck-publishing pipeline, but its publisher injects author-controlled analytics despite documentation saying the portable copy should not.

Review before installing. Use it only for the author's hekouwang workflow, or first remove/replace the hardcoded Cloudflare analytics beacon, replace author CTAs and links with your own placeholders, pin and manually approve dependencies, and confirm the D1 comments privacy behavior before publishing.

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 (4)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:89
Finding

Mandatory Author-Controlled Promotional Content in Generated Output

Content
View full analysis
偷师 AI 大佬 · STEAL THE PLAYBOOK · EP01 · @huiyonghkw
🎁 微信搜 会勇禾口王的AI笔记,回复 工厂 领 AI 内容流水线手册
``` From `scripts/publish.py:386`: ```html
本站演示引擎开源为 Claude Skill · GitHub @huiyonghkw
``` From `scripts/publish.py:717`: ```html

🎁 微信搜 {BRAND},回复 工厂,领「AI 内容流水线手册」。

``` ### Technical Analysis The Skill instructions explicitly require generated decks to contain a private-channel call to action. The reusable deck templates and publisher then hardcode the author's identity, WeChat lead-generation instructions, GitHub links, and promotional copy. This behavior affects the agent's output objective: instead of generating only content requested by the user, the Skill directs the agent to add unrelated third-party promotional material. Because the supplied templates already contain this content, it may survive even when an a ...[truncated 1401 chars]
Remediation
View remediation

other

Error
Location
scripts/publish.py:283
Finding

Hardcoded Author-Linked Cloudflare Analytics Injected into Every Built Page

Content
View full analysis
""") def localize(html: str) -> str: """① 本地 Anthropic 字体绝对路径 → 站内 /fonts/;② 自托管思源黑/宋: 删掉 Google Fonts / loli 外链(preconnect + css2),注入本地 @font-face; ③ 注入 Cloudflare Web Analytics beacon(真人流量统计)。""" html = FONT_ABS_RE.sub("/fonts/", html) html = re.sub(r'\s*]*(?:googleapis|gstatic|loli)[^>]*>', "", html) html, n = re.subn(r']*>', FONT_FACE_CJK, html, count=1) if n: html = re.sub(r']*>', "", html) if "rel=\"preload\"" not in html: pl = PRELOAD_LINKS_V6 if "Mozilla" in html else PRELOAD_LINKS html = html.replace("", "" + pl, 1) if "cloudflareinsights" not in html: html = (html.replace("", CF_BEACON + "\n", 1) if "" in html else html + CF_BEACON) return html ``` The behavior conflicts with the statement in `SKILL.md:54` that the portable copy leaves the analytics token empty: ```markdown > ⚠️ 副本里 **`CF_BEACON_TOKEN` 与 `wrangler.toml` 的 database_id 都留空/占位**——落地新站时填自己的,别沿用他人的(否则流量统计报到别人面板、留言写进别人的库)。 ``` ### Technical Analysis The `localize()` function is applied ...[truncated 2184 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/publish.py:743
Finding

Automatic Installation and Execution of Unpinned Global Dependencies

Content
View full analysis
str | None: exe = shutil.which("wrangler") if exe: return exe if shutil.which("npm") is None: print("\n⚠️ 没有 npm,无法安装 Wrangler。请先装 Node.js。") return None print("\n📥 未检测到 Wrangler,自动安装:npm i -g wrangler …") try: subprocess.run(["npm", "i", "-g", "wrangler"], check=True) except subprocess.CalledProcessError: print("⚠️ Wrangler 安装失败,请手动 `npm i -g wrangler`。") return None return shutil.which("wrangler") ``` From `SKILL.md:134`: ```bash cd 演读DECK && python3 -m venv tools/fenv && tools/fenv/bin/pip install fonttools brotli ``` ### Technical Analysis The default publishing path attempts to install the latest available `wrangler` package globally when no existing executable is found. No package version, lockfile, integrity hash, or reviewed registry state is specified. A global npm installation can modify user-wide or system-wide package directories. Depending on npm configuration and execution privileges, the package installation may also execute lifecycle scripts with broad filesystem access. The Python setup instructions similarly install unpinned versions of `fonttools` and `brotli`. This creates non-reproducible builds and exposes users to upstream compromise, malicious release replacement, or breaking changes. The package name `wrangler` is legitimate; the finding is not based on evidence that the current package is malicious. The risk arises from automatic, unpinned, globally scoped installation and immediate execution. ### Attack Path 1. A user invokes `scripts/publish.py` without Wrangler installed. 2. `ensure_wrangler()` discovers ` ...[truncated 1203 chars]
Remediation
View remediation
npm ci ``` 5. Invoke the locked local executable, such as `node_modules/.bin/wrangler`. 6. Use lockfile integrity metadata and a trusted npm registry configuration. 7. Disable dependency lifecycle scripts where compatible, or review required scripts before installation. 8. Pin Python package versions and hashes in a requirements file: ```text fonttools== --hash=sha256: brotli== --hash=sha256: ``` 9. Install Python dependencies with `pip install --require-hashes -r requirements.txt`. 10. Document the exact reviewed versions and provide a controlled update process. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
assets/functions/api/comments.js:10
Finding

Commenter IP Addresses Are Pseudonymized with a Public Static Salt

Content
View full analysis
b.toString(16).padStart(2, "0")).join("").slice(0, 32); } ``` From `assets/functions/api/comments.js:101-116`: ```javascript const ip = request.headers.get("CF-Connecting-IP") || ""; const ipHash = await hashIP(ip); const now = Math.floor(Date.now() / 1000); // 限频:同 IP 在 RATE_WINDOW 秒内已发过 → 429 const recent = await env.DB.prepare( "SELECT created_at FROM comments WHERE ip_hash = ? ORDER BY id DESC LIMIT 1" ).bind(ipHash).first(); if (recent && now - recent.created_at < RATE_WINDOW) { return json({ error: "发得太快啦,歇口气再来" }, 429); } const res = await env.DB.prepare( "INSERT INTO comments (page, nickname, content, created_at, ip_hash, approved) VALUES (?, ?, ?, ?, ?, 1)" ).bind(page, nickname, content, now, ipHash).run(); ``` ### Technical Analysis The backend does not store plaintext IP addresses, but it derives a deterministic identifier using ordinary SHA-256 and a salt embedded publicly in the source code. The digest is truncated to 128 bits. A public constant does not provide cryptographic secrecy. An attacker who obtains the comments database can hash candidate IP addresses using the same constant and compare the results. The candidate space for IPv4 addresses is sufficiently constrained for targeted or large-scale enumeration, especially when probable network ranges or timestamps are known. Because eve ...[truncated 1786 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (37)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/publish.py`(发布脚本)、`scripts/sync-from-harness.sh`(真身→副本单向同步)、`assets/functions/api/comments.js`(留言板后端)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/publish.py`(发布脚本)、`scripts/sync-from-harness.sh`(真身→副本单向同步)、`assets/functions/api/comments.js`(留言板后端)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/publish.py`(发布脚本)、`scripts/sync-from-harness.sh`(真身→副本单向同步)、`assets/functions/api/comments.js`(留言板后端)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/publish.py`(发布脚本)、`scripts/sync-from-harness.sh`(真身→副本单向同步)、`assets/functions/api/comments.js`(留言板后端)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/publish.py`(发布脚本)、`scripts/sync-from-harness.sh`(真身→副本单向同步)、`assets/functions/api/comments.js`(留言板后端)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/publish.py`(发布脚本)、`scripts/sync-from-harness.sh`(真身→副本单向同步)、`assets/functions/api/comments.js`(留言板后端)

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · assets/templates/deck-engine-暖黑.html (reported line 273)May include surrounding context.

html
<main class="deck" id="deck">

  <!-- 01 封面 -->
  <section class="slide cover">
    <div class="stage">
      <div class="kicker an" style="--i:0"><span></span>纯技术科普 · 把概念讲明白 · 零基础友好</div>

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · assets/templates/deck-engine-V6焰彩白.html (reported line 268)May include surrounding context.

html
<main class="deck" id="deck">

  <!-- 01 封面 -->
  <section class="slide cover">
    <div class="stage">
      <div class="kicker an" style="--i:0"><span></span>一个大佬 · 一个反常做法 · 一个你明天能用的方法</div>

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · assets/templates/deck-engine-米白.html (reported line 262)May include surrounding context.

html
<main class="deck" id="deck">

  <!-- 01 封面 -->
  <section class="slide cover">
    <div class="stage">
      <div class="kicker an" style="--i:0"><span></span>一个大佬 · 一个反常做法 · 一个你明天能用的方法</div>

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/留言板-D1.md (reported line 34)May include surrounding context.

md
## 4. 已有防护(改的时候别拆掉)

昵称 ≤24 / 正文 ≤500;`SHA256(salt|IP)` 前 32 位做限频(同 IP 20s 一条,**不存明文 IP**);蜜罐字段 `website`(机器人填了就静默丢);`ensureSchema` 幂等自建表;渲染端 `esc()`(`textContent`→`innerHTML`)防 XSS;`PAGE_RE` 白名单把非法 page(`../etc/passwd`)归 `home`,挡路径注入。

## 5. 部署踩坑

Lp1

High
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill contains undeclared network-capable behavior: it can install Wrangler from npm and deploy to Cloudflare Pages, creating or modifying remote resources. In an agent setting, hidden or insufficiently declared network/publishing capability is dangerous because it can exfiltrate content, change production state, or make unintended public releases without an adequately constrained permission model.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The file is entirely presented in Chinese, including the title and process guidance references, with no indication that language selection is optional or that the skill is region-specific. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown file includes example activation phrases such as "turn this into a deck" and "publish to hekouwang" that are relatively broad and lack clear scope boundaries. The README does not provide negative examples or constraints explaining when the skill should or should not auto-load, increasing the risk of accidental invocation during ordinary conversation.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README advertises very broad natural-language trigger phrases such as making a demo version, adding an episode, or publishing to the site, which can cause the skill to activate in contexts the user did not specifically intend. Because this skill performs content transformation and deployment-related actions, accidental activation could lead to unintended edits or publishing workflows being invoked from ambiguous requests.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest-facing fields and the full operational description are entirely in Chinese, including trigger phrases and usage instructions, with no indication that other languages are supported or that the user can opt into this locale. Under the stated policy, a skill that effectively requires a specific language without user choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The module explicitly stores presenter notes in hidden DOM elements and makes them available in a separate presenter view. Although this is intentional functionality, the notes are still present client-side and can be exposed to anyone who opens the presenter mode or inspects the page, so sensitive script content is not truly protected.

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 the entire interface and instructional content are presented only in Simplified Chinese. This imposes a specific language/locale on all users without any visible opt-in, selector, or explanation that the skill is intentionally region-specific.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest explicitly claims the skill will self-host fonts and use that capability to avoid first-paint font issues, but this template still preconnects to and loads fonts from fonts.googleapis.com/fonts.gstatic.com. That behavior does not match the stated self-hosted-font intent for the deck engine and introduces an external dependency the description suggests should be avoided.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This file declares lang="zh-CN" at the document level, and the visible interface text throughout the deck is fixed in Simplified Chinese. Under the policy, forcing a specific language or locale without user opt-in is a natural-language policy concern unless the locale restriction is explicitly justified or optionality is provided.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document sets lang="zh-CN" and the entire interface copy is written in Chinese, indicating a fixed language/locale choice. Under the policy rule, forcing a specific language without user opt-in or documented justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest describes a reusable DECK publishing pipeline with self-hosted fonts for deployment to Cloudflare Pages, but these font-face declarations reference absolute paths on a local macOS home directory and even another skill directory. In practice this does not implement deployable self-hosting for the published site and diverges from the claimed production behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The page includes a留言板 form and posts nickname, content, page, and honeypot field data to /api/comments via fetch, but there is no visible notice near the form explaining that the message will be transmitted to a backend service or potentially stored and displayed. For a user-generated content feature that collects and publishes input, some disclosure is expected under the missing-warning rule for markdown/code-visible behaviors affecting user data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document declares lang="zh-CN", and the visible interface text throughout the page is Chinese. Under the policy rule, forcing a specific language or locale without user opt-in is a natural-language policy violation unless the restriction is explicitly justified, which is not present here.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The documentation says deployment targets keynote.pages.dev, but the code is configured to deploy to hekouwang.pages.dev. This mismatch can mislead operators and downstream automation into publishing to the wrong production site, which is especially risky for a deployment script tied to a public-facing Pages project.

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

python
# 重写了一半。所以这里实跑一次确认可用,不可用就当没有,走下面的缓存兜底。
    def _usable(exe: str) -> bool:
        try:
            subprocess.run([exe, "--help"], capture_output=True, check=True, timeout=30)
            return True
        except (OSError, subprocess.SubprocessError):
            return False

Static analysis

No suspicious patterns detected.