T09 · Insecure Skill Coding Practices
- Location
scripts/generate_html.py:408- Finding
Shell Command Injection Through Attacker-Controlled Output Paths
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This presentation-generation skill is mostly purpose-aligned, but it needs review because its scripts can automatically invoke shell-based file opening and generated HTML can run untrusted active content.
Review before installing. Use it only on trusted outlines/content, avoid running the generator with attacker-controlled output paths, prefer disabling or removing automatic preview, and vendor or pin external assets/dependencies if you need offline or reproducible presentations.
scripts/generate_html.py:408Shell Command Injection Through Attacker-Controlled Output Paths
scripts/generate_html.py:220Stored HTML and JavaScript Injection in Generated Presentations
{subtitle}
' if subtitle else ''}{subtitle}
' if subtitle else ''}{item.get('description', '')}
assets/template.html:600Mutable Remote JavaScript Is Retrieved and Executed at Presentation Runtime
scripts/generate_pptx.py:18Unpinned Python Dependency Installation Produces Non-Reproducible and Unsafe Builds
Mixing characters from multiple Unicode scripts in a single identifier is a common technique to create visually ambiguous tool names.
Claiming single-file HTML/WebGL/animations while actually producing different output and performing undeclared OS actions creates a trust and execution-boundary problem. Users may handle the generated files or grant capabilities based on inaccurate expectations, and the undeclared macOS open behavior introduces unnecessary shell execution in a content-generation skill.
Claiming single-file HTML/WebGL/animations while actually producing different output and performing undeclared OS actions creates a trust and execution-boundary problem. Users may handle the generated files or grant capabilities based on inaccurate expectations, and the undeclared macOS open behavior introduces unnecessary shell execution in a content-generation skill.
Claiming single-file HTML/WebGL/animations while actually producing different output and performing undeclared OS actions creates a trust and execution-boundary problem. Users may handle the generated files or grant capabilities based on inaccurate expectations, and the undeclared macOS open behavior introduces unnecessary shell execution in a content-generation skill.
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
每一页都是一个 <section class="slide ...">。必须包含 data-theme 属性(light 或 dark),JS 翻页时会根据这个属性切换背景。
<section class="slide light" data-theme="light"> <!-- 浅色页 -->
<section class="slide dark" data-theme="dark"> <!-- 深色页 -->
<section class="slide light hero" data-theme="light"> <!-- Hero 页:浅色 + 薄遮罩透出 WebGL -->
<section class="slide dark hero" data-theme="dark"> <!-- Hero 页:深色 + 薄遮罩 -->
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.
每一页都是一个 <section class="slide ...">。必须包含 data-theme 属性(light 或 dark),JS 翻页时会根据这个属性切换背景。
<section class="slide light" data-theme="light"> <!-- 浅色页 -->
<section class="slide dark" data-theme="dark"> <!-- 深色页 -->
<section class="slide light hero" data-theme="light"> <!-- Hero 页:浅色 + 薄遮罩透出 WebGL -->
<section class="slide dark hero" data-theme="dark"> <!-- Hero 页:深色 + 薄遮罩 -->
The script invokes a shell via os.system() using a path derived from user-controlled --output input. Although the path is wrapped in double quotes, shell metacharacters such as embedded quotes can still break out of the quoting context and lead to command injection on macOS when the file is auto-opened.
# 自动打开(macOS)
if sys.platform == "darwin":
os.system(f'open "{output_file}"')
if __name__ == "__main__":
The code invokes a shell via os.system() using a command string built from a file path. Although the path is quoted and the filename is timestamp-based, shell invocation is still unnecessary and unsafe because any future change that makes the path user-influenced could turn this into command injection, and the current behavior also triggers unintended local command execution by auto-opening files.
# 自动打开(macOS)
if sys.platform == "darwin":
if results["html"]:
os.system(f'open "{results["html"]}"')
elif results["pptx"]:
os.system(f'open "{results["pptx"]}"')
This is the same unsafe pattern for the PPTX branch: a shell command is constructed and executed to open a generated file. Even if immediate exploitability is limited by current filename generation, using the shell for local file opening expands attack surface and is not required for the skill's core function.
if results["html"]:
os.system(f'open "{results["html"]}"')
elif results["pptx"]:
os.system(f'open "{results["pptx"]}"')
if __name__ == "__main__":
The script invokes a shell command via os.system() using a path derived from user-controllable input (--output). Even though the path is wrapped in double quotes, shell metacharacters such as embedded quotes can still break out of the quoting context and lead to command injection on macOS when the file is auto-opened.
# 自动打开(macOS)
if sys.platform == "darwin":
os.system(f'open "{output_file}"')
if __name__ == "__main__":
The trigger phrases include very generic requests like '做 PPT' and '生成演示', which are likely to match normal user intent outside this specific skill. Overly broad activation can cause unintended invocation of the skill, leading to surprise file reads or generation behavior that the user did not explicitly request.
The statement "Skills 就是 Skills,不中英混译" prescribes a fixed language usage rule and does not indicate that users may choose their preferred language or locale. This can conflict with language-choice policies because it imposes a linguistic constraint without opt-in or documented justification.
The skill explicitly instructs file reads, file writes, and shell execution (for example reading template files and running a local open command), but it does not declare any tool scope or allowed-tools boundary. That creates an authorization and review gap: an agent may exercise more capability than users expect, increasing the risk of unintended filesystem access or command execution.
The document declares lang="zh-CN", which hard-codes a specific language/locale for the entire skill artifact. Under the policy, locale constraints should either be optional/user-selectable or clearly justified as region-specific; this file provides neither.
The template fetches Google Fonts from third-party domains, which means the generated presentation is not actually self-contained and will make outbound network requests when opened. This creates privacy, tracking, availability, and supply-chain risk: viewing the deck leaks client metadata to external services and the presentation can partially break if those resources are blocked or modified.
The template loads lucide from an external CDN at runtime, so opening the generated HTML executes third-party JavaScript in the viewer's browser. This is more serious than fonts because it introduces direct script supply-chain risk: if the CDN content changes, is compromised, or is blocked, the presentation may execute untrusted code or fail entirely.
These lines instruct authors to prefer English terms such as 'Skills / Harness / Pipeline / Workflow' and to avoid translating them. This imposes a specific language choice in natural-language guidance without offering the user a choice or documenting a justified locale-specific requirement.
Line L042 states '字体分工是本模板最重要的规则,严禁混用', and the surrounding section prescribes fixed Chinese font classes such as Noto Serif SC/Noto Sans SC for titles and body text. This imposes a specific language/locale presentation convention rather than offering a user choice, which matches the policy category for forced language or locale behavior.
This markdown file is written as prescriptive guidance entirely in Chinese and uses imperative instructions such as '生成前必读' and '不要发明新类名' without indicating that other languages are supported. Because the policy applies to natural-language constraints across all file types, this reads as a default language requirement rather than a user-selectable locale.
The instruction explicitly tells the skill to tell the user a fixed Chinese phrase in the dialogue. This imposes a specific language on user-facing output without any opt-in or alternative language handling, which matches the language/locale policy violation category.
The manifest describes automatic generation of magazine-grade PPTs with AI-driven layout, color, charts, animations, and WebGL fluid background. In this file, the code merely parses a local JSON outline or creates a trivial three-slide fallback structure, then emits HTML/CSS with simple navigation and a fade-in effect; there is no AI generation, chart creation, WebGL background, or substantive automation matching those claims.
The script executes a shell command to open a file without warning or confirmation, creating unexpected side effects. In this codebase that is more dangerous than a mere UX issue because the opened HTML embeds unescaped user-controlled title, subtitle, content, and image values, which can result in immediate active content execution when viewed.
The manifest states the skill generates a '单文件 HTML 横向翻页演示文档', implying HTML output as the product. However, the module docstring and implementation explicitly support 'HTML 和 PPTX 双格式输出' and invoke PPTX generation paths, expanding the behavior beyond the described scope.
This code file contains natural-language strings that present the skill as Chinese-only, including the top-level description and later CLI help text. The policy requires flagging language or locale constraints when the skill forces a specific language without user opt-in or a clearly justified region-specific scope.
Automatically opening generated files causes local side effects beyond simple file generation and is not clearly justified by the skill description. In skill/plugin contexts, unexpected file execution/opening is more dangerous because it can launch associated applications, trigger browser rendering of generated HTML, and reduce user control over potentially untrusted output.
No suspicious patterns detected.