Back to skill

Security audit

Yuanfang HTML Image

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real image generator, but crafted content or URLs could make it run local commands or reach internal network resources.

Review before installing. Avoid using this skill on untrusted URLs or untrusted article titles until it replaces shell-string execution with argument-array process execution, pins Playwright in a manifest and lockfile, validates and limits all URL fetches, escapes image/CSS values safely, and offers explicit cache controls.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/render.js:217
Finding

Shell Command Injection Through Attacker-Controlled Output Paths

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/extract-brand.js:26
Finding

Server-Side Request Forgery Through Unrestricted Page and Logo Fetching

Content
View full analysis
{ if (!r.ok) throw new Error(`HTTP ${r.status}`); return Promise.all([r.arrayBuffer(), r.headers.get('content-type')]); }) .then(([buf, ct]) => { const mime = ct || 'image/png'; return `data:${mime};base64,${Buffer.from(buf).toString('base64')}`; }); } ``` ```javascript let logoUrl = null; if (ogImage) { logoUrl = ogImage.startsWith('http') ? ogImage : new URL(ogImage, url).href; } else if (appleIcon) { logoUrl = appleIcon.startsWith('http') ? appleIcon : new URL(appleIcon, url).href; } ``` ```javascript async function fetchBrand(url) { const res = await fetch(url, { headers: { 'User-Agent': 'yuanfang-skills/0.1' }, redirect: 'follow', }); if (!res.ok) throw new Error(`HTTP ${res.status} fetching ${url}`); const html = await res.text(); const brand = extractBrandFromHtml(html, url); if (brand.logoUrl) { try { brand.logo = await resolveImageAsDataUrl(brand.logoUrl); ``` A second unrestricted entry point exists in `scripts/extract.js`: ```javascript async function extractFromUrl(url) { const res = await fetch(url, { headers: { 'User-Agent': 'yuanfang-skills/0.1 (+https://github.com/yuanfang)' }, redirect: 'follow', }); if (!res.ok) throw new Error(`HTTP ${res.status} fetching ${url}`); const html = await res.text(); return extractFromHtml(html, url); } ``` ### Technical Analysis Both extraction scripts accept arbitrary URLs and follow redirects without validating the destination scheme, resolved IP address, or network range. The brand extractor intr ...[truncated 1783 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/render.js:71
Finding

HTML and CSS Injection in Generated Browser Documents

Content
View full analysis
` : ''; const qrHtml = resolveQrHtml(content.qr); ``` ```javascript ${baseCSS} ${themeCSS} ${brandOverrideCss} body { margin: 0; padding: 0; width: ${width}px; height: ${height}px; overflow: hidden; } .cover { width: ${width}px; height: ${height}px; } ``` ```javascript function resolveQrHtml(qr) { if (!qr) return ''; if (isImageRef(qr)) { return `QR`; } ``` ```javascript function buildBrandOverrideCss(spec, themeName) { if (!spec || !spec.colors) return ''; const c = spec.colors; const map = { '--accent': c.primary, '--bg': c.background, '--secondary': c.secondary, }; const decls = Object.entries(map) .filter(([, v]) => v) .map(([k, v]) => ` ${k}: ${v};`) .join('\n'); if (!decls) return ''; return `[data-theme="${themeName}"] {\n${decls}\n}\n`; } ``` ### Technical Analysis Textual content such as titles and badges is escaped, but values used in image attributes and generated CSS are not safely handled for their output contexts. `content.brandImage` and image-like QR values are inserted directly into double-quoted `src` attributes. A malicious value containing a quotation mark can terminate the attribute and inject new attributes or markup. Brand color metadata is inserted directly into a `` block without enforcing a valid color grammar. A malicious theme-color value could terminate a declaration, close the style element, and inject HTM ...[truncated 1429 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Error
Location
scripts/render.js:220
Finding

Runtime Execution of an Unpinned Package Through npx

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/extract-brand.js:26
Finding

Unbounded Network Response Buffering Enables Resource Exhaustion

Content
View full analysis
{ if (!r.ok) throw new Error(`HTTP ${r.status}`); return Promise.all([r.arrayBuffer(), r.headers.get('content-type')]); }) .then(([buf, ct]) => { const mime = ct || 'image/png'; return `data:${mime};base64,${Buffer.from(buf).toString('base64')}`; }); } ``` ```javascript async function fetchBrand(url) { const res = await fetch(url, { headers: { 'User-Agent': 'yuanfang-skills/0.1' }, redirect: 'follow', }); if (!res.ok) throw new Error(`HTTP ${res.status} fetching ${url}`); const html = await res.text(); ``` ```javascript async function extractFromUrl(url) { const res = await fetch(url, { headers: { 'User-Agent': 'yuanfang-skills/0.1 (+https://github.com/yuanfang)' }, redirect: 'follow', }); if (!res.ok) throw new Error(`HTTP ${res.status} fetching ${url}`); const html = await res.text(); ``` ### Technical Analysis The extraction functions fully buffer arbitrary HTML and image responses using `res.text()` and `r.arrayBuffer()`. They do not enforce request deadlines, response byte limits, MIME restrictions, image dimension limits, or redirect limits beyond the runtime defaults. Base64 conversion further increases memory consumption. Downloaded images may subsequently be passed to image-processing libraries, where specially constructed or extremely large images can consume substantial memory and CPU. ### Attack Path 1. An attacker supplies a URL for a server they control or causes a page to advertise a malicious image URL. 2. The server responds extremely slowly, never completes the ...[truncated 708 chars]
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 (41)

Vague Triggers

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger terms include very broad everyday words such as “图片”, “封面”, and “海报”, which can match many unrelated user requests and cause the skill to activate unexpectedly. In this skill’s context, accidental activation is more dangerous because the workflow then encourages automatic URL fetching and local caching, potentially processing user-supplied pages and storing derived data without the user clearly intending to invoke this capability.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/render.js --theme <theme> --layout cover --platforms <ids>

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/render.js --theme <theme> --layout cover --platforms <ids>

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/render.js --theme <theme> --layout cover --platforms <ids>

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill instructs the agent to automatically fetch a URL and extract logo, theme color, fonts, and page content, but the user-facing flow does not clearly require prior consent before that collection begins. This creates a privacy and transparency risk: visiting a user-provided URL may reveal network metadata and collecting page assets/content may exceed what the user expected from a simple image-generation request.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill states that extracted brand data is cached in ./.yuanfang/brand-specs/<domain>.json for 7 days and shared via the project workspace, but this persistence is not surfaced as a prominent warning before collection. In context, this makes the issue more serious because cached artifacts may contain user-supplied domains, extracted branding, and other derived data that can persist in source-controlled workspaces and be exposed to collaborators unintentionally.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

SQP-3 applies to all file types and covers language or locale policy violations. The file consistently presents instructions and output descriptions only in Chinese, with no indication that the user can opt into another language or that the skill is intentionally limited to a Chinese-speaking or region-specific context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This script performs outbound network requests to arbitrary user-supplied URLs and persists the fetched brand data under the local .yuanfang/brand-specs cache without any explicit user warning or consent beyond CLI behavior. In an agent/skill context, that can expose sensitive browsing targets to remote servers and leave artifacts on disk, which is a meaningful privacy and transparency issue even if the code appears intended for normal functionality.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

The script constructs a shell command that invokes npx playwright screenshot without pinning an exact package version. npx may download and execute whatever version is currently resolved from the registry or local environment, creating a supply-chain risk where unexpected or malicious code could run during rendering.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The natural-language comment and implementation state that Chinese is the default primary use case and unconditionally return lang: 'zh-CN' for all non-RTL content. This imposes a specific locale on rendered output without offering a user choice or documenting an opt-in, which matches the language/locale policy violation criteria.

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 root element sets lang="zh-CN", which forces a specific language/locale in the rendered output. Under the policy, locale constraints should either be user-selectable or clearly justified as region-specific; this file provides neither.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The template name and description are written only in Chinese, which indicates a language-specific constraint in natural-language metadata. There is no accompanying indication that users can choose another language or that the locale restriction is intentionally limited to a China-specific use case.

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 tag hard-codes lang="zh-CN", which imposes a specific language/locale on all rendered output. Under the stated policy, locale-specific behavior should either be user-selectable or clearly documented as justified for a region-specific skill.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The HTML root element sets lang="zh-CN", which enforces a specific language/locale in the rendered output. Under the policy rules, forcing a locale without user opt-in or 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
93% confidence
Finding

The document root sets lang="zh-CN", which hard-codes a specific language/locale for the skill output. Under the policy criteria, forcing a locale without user opt-in or clear 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
94% confidence
Finding

The HTML root element sets lang="zh-CN", which forces a specific language/locale in the rendered output. Under the policy, locale constraints should either be optional for the user or clearly justified as region-specific, and no such opt-in or justification appears in this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown file contains user-facing instructions and parameter descriptions exclusively in Chinese, such as the section titles and notes. Under the policy, forcing a specific language without offering a language or locale choice can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

This is a markdown file, so SQP-2 applies to omissions in the skill description. The examples show fetching content from a URL and redirecting output to content.json, which can affect privacy and local data, but the document does not include any warning about network access or overwriting/creating local files.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

This markdown file contains user-facing natural-language instructions only in Chinese, and it does not offer an alternative language, opt-in, or state that the skill is intentionally limited to a Chinese-speaking audience. Under the policy, forcing a specific language without user opt-in can be a locale/language 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 markdown file contains user-facing guidance exclusively in Chinese, including headings, descriptions, and recommendations. Under the policy rule, forcing a specific language without user opt-in can be a natural-language policy violation when no justification or alternative language option is provided.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code performs an outbound HTTP request to a user-provided URL and sends request metadata including a custom User-Agent, but there is no confirmation prompt, user-facing log/print, or explanatory comment/docstring disclosing that network activity. For a code file, outbound transmission of user-supplied data should have some visible disclosure unless clearly warned elsewhere.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The comment and thrown error say the renderer refuses to proceed until the user confirms logo, brand name, theme, and platform. However, the actual gate at L404-L406 only checks whether theme is default and whether brand-related fields are absent; it does not verify that platforms were explicitly chosen, and rendering still proceeds with default platforms when those conditions are not met.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The HTML root element sets lang="zh-CN", which forces a specific language/locale in the rendered output. For a generic template, this is a natural-language locale policy concern because the file does not offer a user choice or explain why Chinese is required.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The template name, description, and brand fields are written entirely in Chinese, and the font stack explicitly prioritizes a Chinese locale font. This can indicate a language/locale constraint without any visible opt-in or note that the template is region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The HTML root sets lang="zh-CN", which forces a specific language/locale in the rendered output. Under the policy, locale constraints should either be user-selectable or clearly documented as justified for a region-specific use case.

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.js:223

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
tests/visual-regression.test.js:46