Back to skill

Security audit

Structured PDF Export

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a local PDF-export helper, but its documented local web server can expose generated files beyond localhost and the HTML template accepts unescaped title/subtitle input.

Review this before installing if you may export sensitive data or run on a shared/reachable machine. Safer use would bind the HTTP server to 127.0.0.1, use a unique per-run temporary directory, escape HTML fields, and manually confirm no confidential content is included before sending the PDF.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/generate_table_pdf.py:19
Finding

Unescaped User Input Allows HTML and Script Injection

Content
View full analysis
{title} ``` ```python

📊 {title}

{subtitle}

``` The values originate from command-line arguments and are passed directly to the template: ```python parser.add_argument('--title', default='表格', help='表格标题(必需)') parser.add_argument('--subtitle', default='OpenClaw 结构化数据可视化', help='副标题') ``` ```python html_content = generate_html_template(args.title, args.subtitle) ``` ### Technical Analysis The `title` and `subtitle` values are interpolated directly into an HTML document without context-appropriate escaping. An attacker who can influence either command-line argument can terminate the surrounding HTML element and inject arbitrary markup. For example, a crafted title could close the `` element and add a script: ```text ``` Because the documented workflow instructs the Agent to serve and open the resulting file in a browser, injected JavaScript may execute in the local HTTP origin. The injected code could manipulate the generated document, falsify the content exported to PDF, or request other files exposed by the same temporary-directory HTTP server. The vulnerability does not, by itself, grant arbitrary operating-system command execution. Its direct scope is the rendered browser document and resources accessible through the local server origin. ### Attack Path 1. An attacker supplies or influences t ...[truncated 1274 chars]
Remediation
View remediation
{safe_title}

📊 {safe_title}

{safe_subtitle}

''' ``` Additional hardening measures should include: 1. Treat title and subtitle values as plain text, not trusted HTML. 2. If formatted input is required, process it with a strict HTML allowlist sanitizer. 3. Add a restrictive Content Security Policy, such as: ```html ``` 4. Add tests using payloads containing `

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:94
Finding

Documented HTTP Server Binds to All Network Interfaces

Content
View full analysis
"$TEMP_DIR/server.log" 2>&1 & ``` The helper script prints the same unsafe command: ```python print(f" cd {temp_dir} && python3 -m http.server 8888 > server.log 2>&1 &") ``` ### Technical Analysis Python's `http.server` listens on all available interfaces by default when no `--bind` address is supplied. Consequently, the server is not restricted to `localhost`, even though the documentation directs the browser to a local URL and describes the process as local-only. Any host capable of reaching the system on the selected port may request files beneath the served temporary directory. The server also provides directory listings when an index file is absent, making file discovery straightforward. The use of the fixed port `8888` makes the service easier to identify and probe. Directory permissions such as mode `0700` do not prevent disclosure through the HTTP server because the server process reads the files using the current user's privileges and transmits them to network clients. ### Attack Path 1. The Agent generates HTML or related export data in `.pdf-export-tmp`. 2. The Agent follows the documented command and starts `python3 -m http.server 8888`. 3. Python binds the listener to all available interfaces rather than only loopback. 4. An attacker on a reachable network discovers or already knows that port 8888 is in use. 5. The attacker connects to `http://:8888/`. 6. The server returns a directory listing or a known generated filename. 7. The attacker downloads the generated HTML, logs, or any other files placed in the served directory. 8. Exposure continues until the server is terminated and ...[truncated 657 chars]
Remediation
View remediation
"$TEMP_DIR/server.log" 2>&1 & ``` Apply the same correction to the command printed by the helper script: ```python print( f" cd {temp_dir} && " f"python3 -m http.server 8888 --bind 127.0.0.1 " f"> server.log 2>&1 &" ) ``` Additional hardening measures should include: 1. Prefer an operating-system-assigned random port instead of fixed port 8888. 2. Verify the listening address after startup. 3. Serve a unique per-export directory containing only the intended HTML file. 4. Disable directory listing by using a minimal custom handler or a browser-supported local-file workflow. 5. Ensure cleanup occurs in a `finally` block so the server is terminated after errors. 6. Use firewall controls as defense in depth, not as a substitute for loopback binding. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/generate_table_pdf.py:145
Finding

Existing Temporary Directory Permissions Are Not Corrected

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

声明描述的是一个会自动完成端到端 PDF 导出与发送流程的技能。但实际代码只是一个辅助脚本:检查/创建工作目录和临时目录,生成静态 HTML 模板文件,并在终端打印需要人工执行的命令。代码中没有任何启动 http.server 子进程、调用浏览器工具、执行 PDF 导出、调用 Message 工具发送文件或删除临时目录的实现;也没有将输入的结构化内容转换成表格,只是留下 HTML 注释占位让用户后续手动编辑。因此其实际行为显著弱于且不同于声明的自动化能力,属于描述与行为不匹配。

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 223)May include surrounding context.

md
python3 scripts/generate_table_pdf.py --title "技能清单"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
python3 scripts/generate_table_pdf.py --title "技能清单"

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill instructs the agent to read environment variables and write files, create directories, and manage temporary artifacts, but it does not declare corresponding tool scope such as permissions or allowed-tools. This weakens least-privilege controls and can lead to unintended access to local paths or filesystem side effects when the skill is invoked.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

L003 明确要求“文件名用中文描述性表述”,这是对输出语言/locale 的强制约束。文档中未提供用户选择其他语言或说明这是仅面向特定中文区域/合规场景的限制,因此构成语言/locale 策略风险。

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

创建专用临时目录

mkdir -p "$TEMP_DIR" || { echo "❌ 无法创建临时目录"; exit 1; } chmod 700 "$TEMP_DIR"

text

### 1️⃣ 准备 HTML(结构化布局)

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
| **权限检查** | 验证目录存在、可写、可读 | 单用户有效;多用户需协调 |
| **进程管理** | 保存 PID、验证停止 | 无法验证进程所有权 |
| **敏感数据** | 手动审查内容 | 不支持自动扫描 |
| **临时文件** | 专用目录 + `chmod 700` | 防止其他本地用户访问 |

## 使用辅助脚本快速开始

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring, CLI examples, help text defaults, and generated HTML all assume Chinese-language output and a zh-CN locale. This is a natural-language policy concern because the skill effectively forces a specific language/locale without any opt-in or alternative selection.

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 template fixes the document language to zh-CN, which imposes a locale choice on all generated output. Because the script does not expose a user choice or justify a region-specific constraint, this matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Manifest 描述该技能会“自动触发:创建 HTML → 启动本地服务器 → 打开浏览器 → 转成 PDF → 发送 + 清理临时文件”,而本脚本在 main 中仅创建 HTML 文件,并通过 print 输出需要用户或其他组件手工执行的命令。该行为与所宣称的自动化导出/发送能力存在明显语义落差,不是单纯实现细节差异。

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

epilog 中把“启动服务器并打开浏览器 → 生成 PDF → 复制到工作目录 → 发送给用户并清理”描述成该工具的完整流程,容易让开发者理解为脚本会落实这些操作。实际上代码只在 L226-L242 打印建议命令,没有执行这些步骤,文档表述与真实行为不一致。

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.