T09 · Insecure Skill Coding Practices
- Location
scripts/generate_panel.py:904- Finding
Automatic Disclosure of Source-Derived CSS Metadata to External LLM Providers
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly matches its HTML editor purpose, but it can automatically send CSS metadata from a local HTML file to Anthropic or OpenAI whenever ambient API keys are present.
Install only if you are comfortable with a local HTML conversion tool that may contact Anthropic or OpenAI when those API keys are present in the environment. For confidential HTML, run it in an environment without those keys or block network access; avoid --skip-checks unless manually reviewing the generated HTML, and remember that edits are saved in browser localStorage until cleared or reset.
scripts/generate_panel.py:904Automatic Disclosure of Source-Derived CSS Metadata to External LLM Providers
The code reads API credentials from environment variables and sends them in authenticated requests to a third-party LLM service. While using an API key in an Authorization header is expected, the security issue is that project-derived content (variables_info built from parsed HTML/CSS selectors and values) is transmitted off-box for a non-essential feature without explicit user consent or strong scoping controls, creating a data exfiltration risk in a tool whose primary purpose is local HTML visual editing.
import requests
if api_type == 'anthropic':
resp = requests.post(
'https://api.anthropic.com/v1/messages',
headers={
'x-api-key': api_key,
This path sends an OpenAI API key and project-derived labeling input to an external API for semantic label generation. The concern is not merely that the key is used, but that an unrelated editing workflow can silently export internal HTML/CSS structure and content-derived metadata to a third party, which is a meaningful privacy and confidentiality exposure.
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}',
Documenting a '--skip-checks' flag that disables sanity checks increases the chance that an agent or user will generate and trust malformed or unsafe transformed HTML without validation. In the context of a tool that injects CSS/JS into HTML and rewrites output, bypassing verification can suppress safeguards meant to catch bad mappings, broken injection order, or unsafe output conditions.
python html-visual-editor/scripts/adapt.py your-report.html --force --skip-checks
⚠️
--skip-checksforces output even if some checks fail. Review the result manually.
The repeated emphasis that '--skip-checks' 'forces output even if some checks fail' confirms that the tool can be instructed to ignore failed validations and still write modified HTML. For an agent skill that may be invoked automatically, this weakens trust boundaries by enabling production of altered files after failed integrity or compatibility checks, which could propagate broken or insecure artifacts.
python html-visual-editor/scripts/adapt.py your-report.html --force --skip-checks
> ⚠️ `--skip-checks` forces output even if some checks fail. Review the result manually.
## 📺 Demo
声明描述的是一个完整的所见即所得 HTML 编辑器/样式面板系统,而代码片段仅覆盖其中一个较底层的辅助部分:解析 HTML 内嵌 CSS、识别 CSS 变量、分类并建立索引。代码没有任何 DOM 注入、前端交互、编辑器面板、撤销保存导出、Prompt 生成功能。虽然代码中有中英文标签生成与样式语义分组,这可被视为支撑样式面板的数据准备,但远不足以支撑声明中的主要用途。因此代码实际行为与声明的主功能存在明显且实质性的不匹配。
The description promises a feature-rich HTML visual editing system, but the code chunk only diagnoses whether an HTML file has sufficient CSS context for such a tool to work. Its behavior is limited to reading an HTML file, parsing style/link tags with regex, checking local/remote CSS availability, counting CSS variables and inline styles, then returning a verdict like ready/need-files/need-fetch/unsupported. That diagnostic role may support the broader editor workflow, but by itself it does not implement the declared core functionality. Therefore the supplied code does not accurately represent the declared purpose.
声明描述的是一个前端/HTML 转换与编辑器注入技能,核心能力应是修改静态 HTML、生成可视化编辑界面并提供编辑与导出功能。而提供的代码仅是 verify.py,一个离线/后处理校验模块,主要用途是验证某个 HTML 输出是否满足既定规范。它不会注入编辑器、不会实现可视化编辑,也不会完成描述中的 AI Prompt、生成功能、i18n 或导出逻辑。虽然其中检查项与“html visual editor”结构相关,说明它服务于该系统的质量保障流程,但这只是支持性验证代码,不是声明中的主要技能实现。因此代码行为与声明用途存在明显且实质性的偏差。
Referenced artifact was not completely inspected
- 不修改 `assets/editor-core.js`,所有适配逻辑放在 scripts 和 window.X 常量里。
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
parser.add_argument('--diagnose-only', action='store_true', help='仅诊断不生成输出')
parser.add_argument('--fetch', action='store_true', help='允许下载远程 CSS 文件')
parser.add_argument('--force', action='store_true', help='强制覆盖已有编辑器注入')
parser.add_argument('--skip-checks', action='store_true', help='跳过 sanity checks,强制输出(用于复杂布局)')
args = parser.parse_args()
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
parser.add_argument('--diagnose-only', action='store_true', help='仅诊断不生成输出')
parser.add_argument('--fetch', action='store_true', help='允许下载远程 CSS 文件')
parser.add_argument('--force', action='store_true', help='强制覆盖已有编辑器注入')
parser.add_argument('--skip-checks', action='store_true', help='跳过 sanity checks,强制输出(用于复杂布局)')
args = parser.parse_args()
The markdown describes exporting the result as a new HTML file, which affects user data and filesystem output. Aside from the --skip-checks caution, the README does not prominently warn users that the tool writes generated HTML output and may overwrite paths when used with options like -o ... --force.
This README is a markdown file, so vague-trigger review applies. The suggested agent prompts like "Make this HTML editable" and "Add a style panel to this page" are broad, natural requests that could overlap with ordinary conversation, and the file does not provide constraints or negative examples clarifying when the skill should or should not activate.
The skill advertises and instructs execution of Python scripts that read input HTML, write modified HTML, inspect environment variables, and may use networked LLM APIs, yet it declares no explicit tool or permission scope. This weakens least-privilege boundaries and can cause users or agents to run code with broader filesystem, shell, and network access than the metadata suggests.
The description contains very broad trigger phrases such as generic requests to 'make HTML editable' or 'edit HTML without code,' increasing the chance the skill auto-matches unrelated user intents. Overbroad routing can cause unintended execution of file-modifying tooling on documents the user did not specifically intend to transform.
The documentation does not prominently warn that the tool writes a new HTML file and injects JavaScript/CSS editor code into the document. Users may treat the output as a clean or minimally changed HTML artifact and unintentionally open, share, or deploy a modified file containing active editor functionality and localStorage interactions.
The manifest describes '6 套场景风格 Prompt 一键复制给 AI 重塑样式', but the broader editor description also presents style panels and presets as part of the visual editing experience. Here, applyPreset refuses all non-original presets while copyStylePrompt merely copies instructions for an external AI, meaning the advertised style capability is not actually implemented as editor-side style application.
The docstring on L0760 says this function applies a preset, which implies the style presets described in the manifest are actually actionable in the editor. In code, L0762-L0764 explicitly reject any preset other than original, so the implementation contradicts the stated purpose of the function and undermines the manifest claim of built-in style preset application.
This code automatically saves edited text and style state, including user-authored HTML content, into localStorage and later restores it. While some UI strings elsewhere mention autosave, the save/load operations themselves do not provide an explicit user-facing warning at the point of persistence, and this behavior affects user data retention across sessions.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
});
}
} catch(e) {
console.warn('Failed to load saved state:', e);
}
}
The exportHTML flow creates and saves a full HTML file containing the user's current edits, which is a file-write operation with lasting effects. Although function names and success toasts indicate export, there is no explicit confirmation or warning before the file is written or download is triggered.
Multiple visible strings in the template are written directly in Chinese, such as the panel title, tab labels, hints, and reset action. This creates a natural-language locale constraint without any user opt-in or clear documentation that the skill is intentionally region-specific, which matches the language/locale policy violation criteria.
The prompt explicitly requires output in Chinese for the role name and provides all naming guidance in Chinese, effectively enforcing a specific language. This is a natural-language policy concern because no user opt-in or documented region-specific justification is present in the file.
This Python file contains user-facing documentation and CLI help text entirely in Chinese, and later runtime messages are also emitted in Chinese. That imposes a specific language/locale on all users without any visible opt-in or alternate locale support, which matches the language-policy violation criteria.
The --fetch option indicates the script may download remote CSS files, which is a network operation that can transmit system or request metadata. While the flag name suggests fetching, the visible help text does not warn about network access, external requests, or possible privacy implications.
The module introduces external LLM API invocation and secret consumption for label generation, which is not necessary to fulfill the core function of generating a visual HTML editor panel. That mismatch increases risk because users may reasonably expect a local transformation tool, not one that can contact external providers and process extracted project data.