Back to skill

Security audit

easy-html

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real HTML-conversion skill, but it expands into unpinned and dynamically loaded code, third-party scripts, uploads, and publishing without enough guardrails.

Install only if you are comfortable reviewing generated HTML before sharing it, using trusted/pinned dependencies, and avoiding private documents or local images unless you control the upload and hosting destination. Treat inherited HTML as untrusted unless it has been sanitized, and prefer offline or bundled chart assets for sensitive reports.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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 (3)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:28
Finding
Unpinned Executable Third-Party Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:28-31` **Vulnerability Type**: Unpinned Python dependencies and unsafe supply-chain trust **Risk Level**: Medium ### Complete Code Snippet ```markdown ## 安装 ```bash pip install html-golive # 提供 19 套主题 CSS 引擎 + 可选的发布能力 pip install openpyxl # 可选:读 .xlsx 时需要 ``` ``` The same unpinned installation instruction also appears in `README.md:31-35` and `references/PUBLISH.md:14-17`. ### Technical Analysis The installation instructions do not specify reviewed versions or package hashes. Consequently, installation resolves to whatever package release is available from the configured Python package index at that time. This is especially security-sensitive for `html-golive`: the project imports and executes `golive.core.css_style_enhancer` as Python code. It also relies on that dependency for optional publishing. Package installation and subsequent imports therefore execute code with the privileges of the user or agent running the Skill. There is no evidence that the current package is malicious. The vulnerability is the absence of controls that bind installation to a reviewed artifact. A compromised publisher account, malicious future release, package-index compromise, or dependency-resolution substitution could change the effective executable code after this Skill has been audited. ### Attack Path 1. An attacker compromises the `html-golive` publishing account, package repository, or an upstream dependency. 2. The attacker publishes a malicious release under the expected package name. 3. A user or agent follows the documented `pip install html-golive` command. 4. The package manager retrieves the unreviewed current release. 5. Malicious code executes during installation, import, theme application, or publishing. 6. The payload obtains the same filesystem, network, environment-variable, and process privileges as the invoking user. ### Impact Assessment Successful exploitation could r ...[truncated 614 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin each dependency to a reviewed exact version, for example: ```text html-golive==X.Y.Z openpyxl==X.Y.Z ``` 2. Maintain a lock file containing cryptographic hashes and install with hash verification: ```bash pip install --require-hashes -r requirements.txt ``` 3. Review the package's source, release provenance, maintainer identity, and transitive dependencies before updating the pin. 4. Separate the publishing dependency from the local formatting dependency where possible. 5. Run external packages in a restricted environment with only the input and output paths required by the task. 6. Avoid exposing unrelated credentials or sensitive environment variables to theme-processing and publishing commands. 7. Document a controlled update process that requires re-audit before changing dependency versions. ]]>

T03 · Remote Payload Retrieval and Execution

Warning
Location
assets/chart_helper.js:21
Finding
Runtime Retrieval and Execution of Integrity-Free CDN JavaScript<![CDATA[ ## Vulnerability Details **File Location**: `assets/chart_helper.js:21-52` **Vulnerability Type**: Remote payload retrieval and execution without integrity verification **Risk Level**: Medium ### Complete Code Snippet ```javascript var CDN_SOURCES = (window.EH_CHART_CDN && window.EH_CHART_CDN.length) ? window.EH_CHART_CDN : [ "https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js", "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.min.js", "https://unpkg.com/chart.js@4.4.1/dist/chart.umd.min.js", "https://fastly.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js" ]; function cssVar(name, fallback) { var v = getComputedStyle(document.documentElement).getPropertyValue(name); return (v && v.trim()) || fallback; } // Color palette and theme helpers omitted here only from the control-flow path. function loadScript(srcs, i, onok, onfail) { if (i >= srcs.length) { onfail(); return; } var s = document.createElement("script"); s.src = srcs[i]; s.onload = function () { onok(); }; s.onerror = function () { loadScript(srcs, i + 1, onok, onfail); }; document.head.appendChild(s); } ``` The helper is embedded into generated pages by `scripts/apply_layout.py:85-88`: ```python if not args.no_chart: html, c3 = inject_js_body(html, _read(CHART_JS), "data-eh-chart-helper") if c3: done.append("图表助手") ``` ### Technical Analysis When a generated page contains a `canvas[data-eh-chart]` element, the helper creates a script element and retrieves Chart.js from one of four external CDNs. The downloaded response executes with the security context of the generated page. Although the URLs contain a fixed Chart.js version, the code does not verify a cryptographic Subresource Integrity hash. Dynamically created script elements also are not constrained by an included Content Security Policy. If a CDN response, DNS path, package artifact, or configured custom source is compromised, th ...[truncated 1484 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Bundle a reviewed Chart.js distribution inside the Skill and inject it locally rather than downloading executable code at page runtime. 2. If remote hosting is required, emit a static script tag with: - A pinned version. - A verified `integrity` hash. - An appropriate `crossorigin` attribute. 3. Add a restrictive Content Security Policy, particularly a narrowly scoped `script-src`. 4. Validate custom CDN entries: - Require HTTPS. - Reject non-HTTP schemes such as `javascript:` and `data:`. - Prefer an explicit host allowlist. 5. Do not automatically inject the chart helper into pages without charts. The current helper avoids retrieval when no chart exists, but omitting the helper entirely further reduces attack surface. 6. Offer a fully offline mode as the secure default. 7. Document that external chart scripts receive access to all data rendered in the page. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/inherit_layout.py:139
Finding
Inherited HTML Preserves Untrusted Active Content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/inherit_layout.py:139-225` **Vulnerability Type**: Unsafe preservation and potential publication of active HTML content **Risk Level**: Medium ### Complete Code Snippet ```python html = open(args.html, encoding="utf-8").read() ``` After adding theme CSS, the original HTML is written back without sanitizing scripts, event handlers, frames, or external resources: ```python # First remove the previous inheritance override block. html = re.sub(r'\n?<style data-eh-inherit="[^"]*">.*?</style>\n?', '\n', html, flags=re.S) # Inject before </head> so the theme overrides the source :root. if re.search(r'</head>', html, re.I): html = re.sub(r'</head>', override + '</head>', html, count=1, flags=re.I) else: html = override + html out = args.output or args.html with open(out, "w", encoding="utf-8") as f: f.write(html) ``` ### Technical Analysis The layout inheritance mode intentionally keeps the source HTML structure intact while injecting theme variables. However, it preserves more than layout: all active content in the original document remains present. No processing removes or validates: - `script` elements. - Inline event handlers such as `onclick` or `onload`. - `iframe`, `object`, or `embed` elements. - Dangerous or unexpected URL schemes. - External scripts, stylesheets, fonts, images, or tracking resources. - Active SVG or other browser-executable markup. Preserving executable content is not required merely to preserve a visual layout. Because the workflow supports publishing the resulting document, an attacker-supplied source page can retain a payload while acquiring the trusted appearance of a themed report. The publication instructions require user confirmation, which is an important mitigating control. Nevertheless, users may reasonably assume that the conversion process produced a safe static page. ### Attack Path 1. An attacker supplies a visually polished HTM ...[truncated 1542 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Sanitize inherited HTML by default using a maintained allowlist-based HTML sanitizer. 2. Remove or reject: - All script elements. - Inline event-handler attributes. - `iframe`, `object`, and `embed` unless explicitly allowed. - `javascript:`, unsafe `data:`, and other active URL schemes. - Active SVG constructs and unexpected external resources. 3. Define separate operating modes: - A safe static-layout mode that strips active content. - An explicit trusted-input mode that preserves scripts only after clear user approval. 4. Inventory external resources and show them to the user before preview or publication. 5. Add a restrictive Content Security Policy to generated pages. A static report should normally disallow scripts entirely unless charts require a specifically approved local script. 6. Preview untrusted HTML in a sandboxed environment without same-origin access, credentials, or privileged browser integrations. 7. Before publishing, perform a final automated scan for script tags, event handlers, active URL schemes, frames, forms, and remote resources. 8. Clearly warn that layout inheritance does not establish the trustworthiness of source HTML unless sanitization has completed. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (29)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
If the actual implementation only injects assets into existing HTML while the skill advertises full conversion, themeing, title/favicon changes, publishing, and layout inheritance, then the user is misled about what data transformations and network actions occur. Misrepresentation is security-relevant here because it can conceal external resource loading and publication behavior that may expose sensitive document content.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
If the actual implementation only injects assets into existing HTML while the skill advertises full conversion, themeing, title/favicon changes, publishing, and layout inheritance, then the user is misled about what data transformations and network actions occur. Misrepresentation is security-relevant here because it can conceal external resource loading and publication behavior that may expose sensitive document content.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
If the actual implementation only injects assets into existing HTML while the skill advertises full conversion, themeing, title/favicon changes, publishing, and layout inheritance, then the user is misled about what data transformations and network actions occur. Misrepresentation is security-relevant here because it can conceal external resource loading and publication behavior that may expose sensitive document content.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
If the actual implementation only injects assets into existing HTML while the skill advertises full conversion, themeing, title/favicon changes, publishing, and layout inheritance, then the user is misled about what data transformations and network actions occur. Misrepresentation is security-relevant here because it can conceal external resource loading and publication behavior that may expose sensitive document content.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
If the actual implementation only injects assets into existing HTML while the skill advertises full conversion, themeing, title/favicon changes, publishing, and layout inheritance, then the user is misled about what data transformations and network actions occur. Misrepresentation is security-relevant here because it can conceal external resource loading and publication behavior that may expose sensitive document content.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the actual implementation only injects assets into existing HTML while the skill advertises full conversion, themeing, title/favicon changes, publishing, and layout inheritance, then the user is misled about what data transformations and network actions occur. Misrepresentation is security-relevant here because it can conceal external resource loading and publication behavior that may expose sensitive document content.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the actual implementation only injects assets into existing HTML while the skill advertises full conversion, themeing, title/favicon changes, publishing, and layout inheritance, then the user is misled about what data transformations and network actions occur. Misrepresentation is security-relevant here because it can conceal external resource loading and publication behavior that may expose sensitive document content.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The module dynamically imports and executes Python code from an environment-controlled file path (`EASY_HTML_CSS_ENGINE`) and from attacker-influenced local directories such as the current working directory. That means anyone who can influence the runtime environment or place files in searched locations can achieve arbitrary code execution when the skill loads the CSS engine. In a content-conversion skill, treating a theme engine as executable Python rather than trusted packaged data makes this especially dangerous because the feature can be triggered during normal operation.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The README explicitly documents a publish step for generated HTML but does not warn users that the output may contain sensitive source content and, once published, can become publicly accessible. In this skill's context, inputs may come from reports, spreadsheets, Word documents, or images, so users could unintentionally expose confidential business or personal data by following the documented workflow.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill describes capabilities that involve environment access, file writes, and network use, but it does not declare any explicit tool scope or permission boundaries. That creates ambiguity for the orchestrator and reviewers, increasing the chance the skill can access or invoke more capability than users reasonably expect, especially around publishing and external asset loading.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The top-level description advertises publishing as a live page but does not clearly warn that publication can make the user's content publicly accessible. This is dangerous because users may provide internal documents, tables, or converted office files expecting local formatting, then inadvertently expose sensitive information when a later publish step is invoked.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger phrases are broad enough to match routine requests like 'make this pretty' or 'turn this into a web page,' which can cause the skill to activate on unrelated or sensitive content without clear user intent. In this skill's context, accidental activation is more dangerous because the workflow includes writing files, optional publishing, and external asset loading, increasing the chance of unintended data exposure.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The natural-language guidance and user-visible fallback text are written only in Chinese, and the file does not indicate that the skill is region-specific or that users may choose another language. Under the policy, forcing a specific language without opt-in is a locale/language policy violation.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
This helper dynamically loads executable JavaScript from public CDNs at runtime, which introduces a supply-chain and privacy risk beyond a purely local HTML conversion feature. If a CDN, mirror, or configured override source is compromised, blocked, or replaced, the generated page will execute untrusted code in the viewer's browser.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The fallback message shown to end users is hardcoded as Chinese text only, with no mechanism for locale selection or opt-in. This can force a specific language experience on users outside that locale and violates the language-choice policy unless the skill is explicitly documented as region-specific.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This markdown file contains user-facing instructional content exclusively in Chinese, and there is no indication that the skill is region-specific or that users can opt into another language. That creates a natural-language policy concern under the language/locale rule because it implicitly forces a specific language experience.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
Line L43 states '中文优先', directing labels and explanatory text to be in Chinese by default. This is a natural-language locale policy constraint, and the file does not indicate that users may choose another language or opt in to the Chinese-only preference.

Context-Inappropriate Capability

Medium
Confidence
94% confidence
Finding
The documentation explicitly instructs the agent to upload local images to arbitrary external image hosting or object storage in order to preserve them in generated HTML. That expands the skill from local content transformation into network publication/exfiltration behavior, which can leak sensitive local files or user-provided documents to third parties without strong trust, consent, destination restrictions, or data-handling controls.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
This markdown file is written as a skill manual entirely in Chinese, and it does not indicate that the language is optional, configurable, or limited to a justified region-specific audience. Under the natural-language policy rules, forcing a specific language without user opt-in is a locale-policy concern.

Natural-Language Policy Violations

Medium
Confidence
82% confidence
Finding
The title and all operational instructions are written as a mandatory workflow in Chinese, and the file does not indicate that users may choose another language or that the skill is region-specific. This can violate a language/locale policy when a skill implicitly forces one language without user opt-in.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This code file contains natural-language instructions and CLI/help text exclusively in Chinese, including the module docstring and usage examples. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly justified, which is not present here.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This code file contains natural-language documentation and CLI/log strings entirely in Chinese, including the module docstring and runtime messages. The file does not indicate that the tool is region-specific or provide any user language selection, which creates a language/locale policy issue under the stated rule.

Natural-Language Policy Violations

Low
Confidence
77% confidence
Finding
A substantial portion of the skill's instructional content is presented only in Chinese, with no indication that the user can choose another language or locale. This can amount to a language/locale policy issue when the skill experience implicitly forces one language without user opt-in.

Intent-Code Divergence

Low
Confidence
98% confidence
Finding
The file header states that when Chart.js fails, the canvas area will show a failure message plus a fallback original data table. In actual code, both degrade() and degradeAll() replace chart canvases only with a text message and never render any tabular representation of the original data.

Missing User Warnings

Low
Confidence
82% confidence
Finding
This code dynamically fetches and executes a third-party script from multiple public CDN endpoints, which is a network operation that can transmit user/system metadata such as IP address and request headers. The file contains no confirmation, user-visible log, or warning comment informing users that external resources will be contacted at runtime.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/_engine.py:50