Back to skill

Security audit

html-editor

Security checks for vulnerabilities and agentic risk

Overview

The skill coherently creates editable copies of static HTML, with disclosed file changes and optional LLM label generation, but users should be aware cloud calls can occur when API keys are present.

Install this only if you intend to create modified editable copies of local/static HTML. The normal command reads the specified input file and writes an *-editable.html file with injected editor JS/CSS and browser localStorage state. If ANTHROPIC_API_KEY or OPENAI_API_KEY is set, the labeling step may send CSS variable metadata and selectors to that provider; unset those variables to keep labeling offline. Review generated HTML before sharing or deploying it.

Vulnerability Patterns
  • 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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (18)

Tainted flow: 'api_key' from os.environ.get (line 907, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
import requests

        if api_type == 'anthropic':
            resp = requests.post(
                'https://api.anthropic.com/v1/messages',
                headers={
                    'x-api-key': api_key,
Confidence
98% confidence
Finding
The code reads an API key from environment variables and uses it to send a prompt containing analyzed page/style data to Anthropic. While using a credential in an Authorization header is normal, this is still a real security/privacy issue because the skill silently transmits user-derived content to a third-party service not disclosed by the skill description, creating a data exfiltration path.

Tainted flow: 'api_key' from os.environ.get (line 907, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
content = resp.json()['content'][0]['text']
                return json.loads(content)
        elif api_type == 'openai':
            resp = requests.post(
                'https://api.openai.com/v1/chat/completions',
                headers={
                    'Authorization': f'Bearer {api_key}',
Confidence
98% confidence
Finding
The OpenAI branch has the same issue: it pulls an API key from the runtime environment and sends prompt content derived from variables/selectors in the analyzed HTML/CSS to an external API. This creates undisclosed third-party data transmission and enables the skill to leverage host secrets for outbound requests without explicit authorization.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill clearly documents capabilities to read and write local HTML files, invoke Python tooling, access environment variables for API keys, and optionally use networked LLM services, yet it declares no permissions. This creates a transparency and consent problem: an agent or user may invoke it without understanding that it can modify files, persist derived artifacts, and potentially transmit content-derived metadata or prompts to external services when keys are present.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
This module serializes page/style analysis data into a prompt and sends it to external LLM APIs, but the skill description does not disclose that remote processing occurs. For an HTML editor, that context makes the issue more dangerous because users may provide proprietary pages, reports, or internal presentations expecting local-only transformation.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The code accesses ANTHROPIC_API_KEY and OPENAI_API_KEY from ambient environment variables even though the skill's stated purpose does not require external providers. This expands trust boundaries and can cause the skill to consume host credentials unexpectedly whenever those secrets are present.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The verifier extracts script content from attacker-controlled HTML and feeds it to an external Node.js parser. Although `--check` avoids normal execution, invoking a full external runtime on untrusted input can still expose the host to parser bugs, resource exhaustion, or environment-dependent behavior, which is notable in a skill that processes arbitrary HTML.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The README tells agents to act on very broad user prompts like 'Make this HTML editable' or 'Add a style panel to this page' without constraining what files may be modified, what inputs are trusted, or what safety checks must occur first. In an agent setting, this can cause over-broad changes to arbitrary HTML, including untrusted or sensitive files, and may normalize applying DOM/JS injection workflows without explicit scope confirmation.

Vague Triggers

Medium
Confidence
84% confidence
Finding
The description contains many broad trigger phrases such as requests to 'make HTML editable' or 'adjust styles without code', which can match a wide range of ordinary user prompts. In agentic environments, this raises the chance of unintended auto-selection and execution on arbitrary HTML, leading to unexpected file modification or insertion of active editing code into documents the user did not specifically intend to transform.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The introductory description emphasizes convenience features but does not prominently warn that the tool rewrites HTML into a new editable variant and that the resulting page stores state in browser localStorage. Because the generated HTML includes injected editor UI and persistent client-side state, users may open or share the output without understanding the behavioral and privacy implications.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill both accesses LLM API keys and performs outbound requests without clear user-facing disclosure or consent. In practice, this means a user invoking a local HTML-visual-editing workflow could unknowingly trigger third-party processing of their document structure and styling metadata.

External Transmission

Medium
Category
Data Exfiltration
Content
import requests

        if api_type == 'anthropic':
            resp = requests.post(
                'https://api.anthropic.com/v1/messages',
                headers={
                    'x-api-key': api_key,
Confidence
93% confidence
Finding
The hardcoded Anthropic endpoint confirms third-party transmission rather than local processing. This is dangerous mainly due to undisclosed exfiltration of analyzed page/style metadata, not because HTTPS itself is unsafe.

External Transmission

Medium
Category
Data Exfiltration
Content
content = resp.json()['content'][0]['text']
                return json.loads(content)
        elif api_type == 'openai':
            resp = requests.post(
                'https://api.openai.com/v1/chat/completions',
                headers={
                    'Authorization': f'Bearer {api_key}',
Confidence
93% confidence
Finding
The hardcoded OpenAI endpoint likewise indicates direct third-party processing. The risk is amplified by ambient secret use and lack of clear disclosure, which can surprise operators who expected a self-contained editing tool.

External Transmission

Medium
Category
Data Exfiltration
Content
import requests

        if api_type == 'anthropic':
            resp = requests.post(
                'https://api.anthropic.com/v1/messages',
                headers={
                    'x-api-key': api_key,
Confidence
93% confidence
Finding
The hardcoded Anthropic endpoint confirms third-party transmission rather than local processing. This is dangerous mainly due to undisclosed exfiltration of analyzed page/style metadata, not because HTTPS itself is unsafe.

External Transmission

Medium
Category
Data Exfiltration
Content
content = resp.json()['content'][0]['text']
                return json.loads(content)
        elif api_type == 'openai':
            resp = requests.post(
                'https://api.openai.com/v1/chat/completions',
                headers={
                    'Authorization': f'Bearer {api_key}',
Confidence
93% confidence
Finding
The hardcoded OpenAI endpoint likewise indicates direct third-party processing. The risk is amplified by ambient secret use and lack of clear disclosure, which can surprise operators who expected a self-contained editing tool.

External Transmission

Medium
Category
Data Exfiltration
Content
if api_type == 'anthropic':
            resp = requests.post(
                'https://api.anthropic.com/v1/messages',
                headers={
                    'x-api-key': api_key,
                    'anthropic-version': '2023-06-01',
Confidence
90% confidence
Finding
The presence of the Anthropic API host alone is not sufficient to prove abuse, but here it corroborates a real remote data flow in combination with requests.post and prompt construction. The security issue is the undisclosed external transmission of analyzed content from a tool whose description does not mention cloud processing.

External Transmission

Medium
Category
Data Exfiltration
Content
return json.loads(content)
        elif api_type == 'openai':
            resp = requests.post(
                'https://api.openai.com/v1/chat/completions',
                headers={
                    'Authorization': f'Bearer {api_key}',
                    'Content-Type': 'application/json',
Confidence
90% confidence
Finding
The OpenAI host reference similarly corroborates an external transmission path. In context, this is risky because analyzed HTML/CSS metadata may reflect sensitive documents, and users are not told that such data may be sent to api.openai.com.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
"""
    import os

    api_key = os.environ.get('ANTHROPIC_API_KEY', '')
    api_type = 'anthropic'
    if not api_key:
        api_key = os.environ.get('OPENAI_API_KEY', '')
Confidence
97% confidence
Finding
Reading ANTHROPIC_API_KEY from the ambient environment is a real secret-harvesting pattern in a skill that does not clearly justify or disclose remote provider use. This allows the code to opportunistically leverage host credentials whenever available, expanding the impact of the skill beyond its advertised local editing purpose.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
api_key = os.environ.get('ANTHROPIC_API_KEY', '')
    api_type = 'anthropic'
    if not api_key:
        api_key = os.environ.get('OPENAI_API_KEY', '')
        api_type = 'openai'
    if not api_key:
        print("  [warning] 未配置 LLM API,使用启发式 label,可能不如人工命名优雅")
Confidence
97% confidence
Finding
The fallback read of OPENAI_API_KEY has the same issue: it silently searches for another host credential and uses it if present. In a plugin/skill ecosystem, this behavior is especially dangerous because it can unexpectedly bridge local content into external services using secrets unrelated to the user's immediate task.

Static analysis

No suspicious patterns detected.