Back to skill

Security audit

Generate responsive HTML pages suitable for reporting, supporting resizing and screenshot capture.

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but it renders raw report content into local HTML without escaping it before opening it in a browser.

Install only if you will generate reports from trusted text or are prepared to sanitize inputs first. Do not feed it untrusted web content, user submissions, or copied HTML/Markdown until the generator escapes report fields or renders in a sandboxed browser with scripts and network access disabled.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate.py:267
Finding

Unescaped Report Data Enables Stored HTML and JavaScript Injection

Content
View full analysis
{item}" for item in items]) # Prepare context for template context = { "title": data.get("title", "述职报告"), "goal": data.get("goal", ""), "q1_title": data.get("q1", {}).get("title", ""), "q1_subtitle": data.get("q1", {}).get("subtitle", ""), "q1_slogan": data.get("q1", {}).get("slogan", ""), "q1_items": format_list(data.get("q1", {}).get("items", [])), "q2_title": data.get("q2", {}).get("title", ""), "q2_subtitle": data.get("q2", {}).get("subtitle", ""), "q2_slogan": data.get("q2", {}).get("slogan", ""), "q2_items": format_list(data.get("q2", {}).get("items", [])), "q3_title": data.get("q3", {}).get("title", ""), "q3_subtitle": data.get("q3", {}).get("subtitle", ""), "q3_slogan": data.get("q3", {}).get("slogan", ""), "q3_items": format_list(data.get("q3", {}).get("items", [])), "q4_title": data.get("q4", {}).get("title", ""), "q4_subtitle": data.get("q4", {}).get("subtitle", ""), "q4_slogan": data.get("q4", {}).get("slogan", ""), "q4_items": format_list(data.get("q4", {}).get("items", [])), "summary_1": data.get("summary", ["", "", "", ""])[0], "summary_2": data.get("summary", ["", "", "", ""])[1], "summary_3": data.get("summary", ["", "", "", ""])[2], "summary_4": data.get("summary", ["", "", "", ""])[3], } html_content = HTML_TEMPLATE.format(**context) ``` ### Technical Analysis E ...[truncated 3203 chars]
Remediation
View remediation
{escape_text(item)}" for item in items) ``` 2. Escape all scalar fields, including the document title, goal, quadrant titles, subtitles, slogans, and summary values: ```python context = { "title": escape_text(data.get("title", "Default Report")), "goal": escape_text(data.get("goal", "")), # Apply escape_text to every remaining scalar field. } ``` 3. Prefer a template engine with automatic HTML escaping, such as Jinja2 configured with `select_autoescape`, rather than using unrestricted `str.format` interpolation. 4. Validate the complete JSON schema before rendering: - Require the top-level value to be an object. - Require `q1` through `q4` to be objects. - Require text fields to be strings. - Require each `items` value and `summary` to be arrays of strings. - Require exactly four summary entries or handle missing entries safely. - Enforce reasonable length limits to reduce rendering and resource-exhaustion risks. 5. Add a restrictive Content Security Policy to the generated document as defense in depth: ```html ``` 6. Render untrusted reports in a sandboxed, isolated browser context with network access disabled. Do not rely on browser isolation as a substitute for output encoding. 7. Add regression tests containing paylo ...[truncated 141 chars]
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill instructs the agent to execute a Python script and write output files, but it declares no explicit tool restrictions such as allowed-tools or permissions. This creates unnecessary capability exposure: an agent may invoke shell and file-write behaviors without a clearly scoped contract, increasing the chance of unintended command execution or filesystem access when the skill is auto-invoked.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The description uses broad triggers like 'create a report, slide, or summary card from raw content,' which can match many ordinary user requests and cause over-invocation. When combined with shell execution and file creation, this broad routing expands the attack surface by enabling the skill in contexts where the user did not clearly consent to running code or generating local artifacts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The field example for title uses Chinese text and the overall data examples are entirely in Chinese, while the skill does not state that language is selectable or that the locale is intentionally region-specific. This can create an implicit language/locale constraint without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The template sets lang="zh-CN" and the generated report labels are written in Chinese throughout the embedded HTML. For a general-purpose report generator, this forces a specific language/locale without user opt-in, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill instructs the agent to generate HTML locally and open it via a file:// URL in a browser, but it provides no user-facing warning or consent step about creating files or accessing local content. Even if the HTML is intended output, local file rendering can expose sensitive local-path context and normalizes opening generated files without transparency to the user.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.