Back to skill

Security audit

多种格式文档转换/图片OCR

Security checks for vulnerabilities and agentic risk

Overview

The skill is a clearly disclosed third-party document converter, with privacy and local-file safety cautions but no evidence of hidden or malicious behavior.

Install only if you are comfortable sending selected documents and the WDANGZ_API_KEY to wdangz.com. Do not use it for contracts, financial records, credentials, personal IDs, regulated data, or confidential business files, and check the output directory because converted files may overwrite an existing file with the same generated name.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/convert.py:401
Finding
Unbounded buffering and storage of remote conversion responses<![CDATA[ ## Vulnerability Details **File Location**: `scripts/convert.py:401-441` **Vulnerability Type**: Unrestricted resource consumption from a remote response **Risk Level**: Medium ### Complete Code Snippet ```python response = session.get(download_url, timeout=120) if response.status_code != 200: raise Exception(f"下载失败,状态码: {response.status_code}") # 获取目标文件扩展名 target_ext = '.pdf' if conversion_type: # 从转换类型推断目标扩展名 type_to_ext = { 'wordTOpdf': '.pdf', 'excelTOpdf': '.pdf', 'pptTOpdf': '.pdf', 'htmlTOpdf': '.pdf', 'pdfTOdocx': '.docx', 'pdf2docx': '.docx', 'pdfTOxlsx': '.xlsx', 'pdfTOpptx': '.pptx', 'pdfTOhtml': '.html', 'pdfTOjpg': '.jpg', 'wordTOjpg': '.jpg', 'excelTOjpg': '.jpg', 'pptTOjpg': '.jpg', 'wordTOexcel': '.xlsx', 'excelTOword': '.docx', 'imageTOpng': '.png', 'imageTOjpg': '.jpg', 'imageTObmp': '.bmp', 'imageToPdf': '.pdf', 'imageToWord': '.docx', 'imageToTxt': '.txt', 'imageToExcel': '.xlsx', } target_ext = type_to_ext.get(conversion_type, '.pdf') # 生成新文件名格式: 原文件名_目标格式.扩展名 if original_file_name and conversion_type: # 获取原文件名(不含扩展名) name_without_ext = os.path.splitext(original_file_name)[0] # 从转换类型提取目标格式(如 wordTOpdf -> pdf, pdfTOdocx -> docx) if 'TO' in conversion_type: type_suffix = conversion_type.split('TO')[-1].lower() else: type_suffix = conversion_type.lower() file_name = f"{name_without_ext}_{type_suffix}{target_ext}" else: # 备用:使用docId file_name = f"converted_{doc_id}{target_ext}" # 确保输出目录存在 os.makedirs(output_dir, exist_ok=True) output_path = os.path.join(output_dir, file_name) with open(output_path, 'wb') as f: f.write(response.content) ``` ### Technical Analysis The download request does not use streaming and does not impose a maximum response size. Accessing `response.content` causes the `requests` library to buffer the complete response body in process memory before it is written to disk. The so ...[truncated 1753 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Request the result as a streamed response: ```python response = session.get(download_url, timeout=120, stream=True) response.raise_for_status() ``` 2. Define a maximum converted-file size appropriate for the service. 3. Reject a declared `Content-Length` that exceeds the limit, while still enforcing the limit during streaming because that header can be missing or inaccurate. 4. Count downloaded bytes and stop before writing data beyond the limit: ```python MAX_DOWNLOAD_BYTES = 100 * 1024 * 1024 downloaded = 0 with open(output_path, "xb") as output: for chunk in response.iter_content(chunk_size=64 * 1024): if not chunk: continue downloaded += len(chunk) if downloaded > MAX_DOWNLOAD_BYTES: raise ValueError("Converted file exceeds the download limit") output.write(chunk) ``` 5. Download into a temporary file in the destination directory and atomically rename it only after successful validation. 6. Delete partial files when a timeout, size violation, or other exception occurs. 7. Validate the downloaded file's expected media type and file signature where practical. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/convert.py:425
Finding
Deterministic output path silently overwrites existing files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/convert.py:425-441` **Vulnerability Type**: Unsafe file overwrite **Risk Level**: Medium ### Complete Code Snippet ```python if original_file_name and conversion_type: # 获取原文件名(不含扩展名) name_without_ext = os.path.splitext(original_file_name)[0] # 从转换类型提取目标格式(如 wordTOpdf -> pdf, pdfTOdocx -> docx) if 'TO' in conversion_type: type_suffix = conversion_type.split('TO')[-1].lower() else: type_suffix = conversion_type.lower() file_name = f"{name_without_ext}_{type_suffix}{target_ext}" else: # 备用:使用docId file_name = f"converted_{doc_id}{target_ext}" # 确保输出目录存在 os.makedirs(output_dir, exist_ok=True) output_path = os.path.join(output_dir, file_name) with open(output_path, 'wb') as f: f.write(response.content) ``` ### Technical Analysis The output filename is generated deterministically from the source filename and conversion type. The destination is then opened with mode `wb`, which creates a new file or immediately truncates an existing file at the same path. There is no collision check, user confirmation, backup, exclusive file creation, or unique-name generation. Repeating a conversion or placing an unrelated file at the predictable destination therefore causes silent data replacement. The command-line interface also accepts an output directory. The overwrite remains constrained by the filesystem permissions of the process, but any existing file writable by that account and matching the generated destination can be damaged. ### Attack Path 1. A file already exists at the predictable generated destination, such as `report_pdftodocx.docx`, in the selected output directory. 2. The user converts a source file whose name and conversion type generate that same destination. 3. The remote conversion completes and the script constructs the existing path. 4. `open(output_path, 'wb')` truncates the existing file before writing the downloaded content. 5. T ...[truncated 1020 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Refuse to overwrite existing files by default. 2. Use exclusive creation mode (`xb`) so collision detection and file creation occur atomically: ```python with open(output_path, "xb") as output: output.write(data) ``` 3. If the destination exists, generate a unique filename such as `report_pdftodocx_1.docx`, or ask the user for explicit overwrite approval. 4. Add an explicit `--overwrite` option for callers that intentionally want replacement behavior. 5. For robust downloads, write to a unique temporary file in the destination directory, validate it, and atomically move it into place. 6. Preserve or back up an existing destination before any explicitly authorized replacement. 7. Document the collision policy so users know whether existing files are retained, renamed, or replaced. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (11)

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Content
��环境变量(唯一支持方式)

**Windows:**
```powershell
# 临时设置(当前终端会话)
$env:WDANGZ_API_KEY = "你的API密钥"

# 永久设置(用户级别)
[Environment]::SetEnvironmentVariable("WDANGZ_API_KEY", "你的API密钥", "User")
```

**Linux/Mac:**
```bash
# 临时设置
export WDANGZ_API_KEY="你的API密钥"

# 永久设置(添加到 ~/.bashrc 或 ~/.zshrc)
echo 'export WDANGZ_API_KEY="你的API密钥"' >> ~/.bashrc
source ~/.bashrc
```

---

## 📋 技术细节

| 项目 | 说明 |
|-----|------|
| API端点 | `https://www.wdangz.com/api/v1/convert` |
| 文件限制 | 单文件最大 50MB |
| 支持格式 | doc, docx, xls, xlsx, ppt, pptx, pdf, jpg, png, bmp, gif, webp |
| 依赖 | Python 3.x + requests 库 |

---

💡 **Tip:** 只需用自然语言描述你要做什么,我会自动识别转换类型!
Confidence
75% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Credential Access

High
Category
Privilege Escalation
Content
# 敏感文件扩展名(可能包含敏感信息)
SENSITIVE_EXTENSIONS = [
    '.pfx', '.p12', '.key', '.pem',  # 证书文件
    '.env', '.credentials',  # 凭证文件
]
# =====================================
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill uses sensitive capabilities (environment variables and outbound network access) but does not declare any explicit tool scope or permissions boundary. This increases the chance of overbroad execution and weakens user visibility into the fact that local files and API credentials are involved in third-party upload operations.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The manifest description is entirely in Chinese and the usage guidance throughout the file assumes Chinese-language interaction, but there is no indication that users may choose another language. This can violate language/locale policy where skills should not impose a specific language without opt-in or justification.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The invocation examples include broad natural-language phrasing such as asking to convert 'this Excel' or similar everyday requests, which could cause the skill to trigger unintentionally during ordinary conversation. In this skill's context, accidental invocation is more dangerous because it may lead to unintended upload of local documents to a third-party service.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The module docstring and all user-facing warnings/messages are written in Chinese, and the script provides no option for users to select another language. This is a natural-language locale constraint that applies across the skill and may violate organizational language-choice policy when not explicitly justified or opt-in.

Tainted flow: 'output_path' from os.environ.get (line 518, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
output_path = os.path.join(output_dir, file_name)
    
    with open(output_path, 'wb') as f:
        f.write(response.content)
    
    file_size = os.path.getsize(output_path)
Confidence
65% confidence
Finding
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
return output_path


def convert_document(file_path, description=None, conversion_type=None, output_dir=None, api_key=None, skip_security_check=False):
    """
    执行文档转换
Confidence
80% confidence
Finding
The function exposes a `skip_security_check` parameter that disables all local safeguards before uploading files to a third-party conversion service. In this skill context, bypassing checks increases the chance that oversized, unsupported, or obviously sensitive files are sent off-host, creating data leakage risk despite the printed warning banner.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
conversion_type: 转换类型(可选,如果提供则优先使用)
        output_dir: 输出目录(默认与源文件同一目录)
        api_key: API密钥
        skip_security_check: 跳过安全检查(不推荐)
    
    返回:
        转换后的文件路径
Confidence
80% confidence
Finding
Documenting `skip_security_check` as a supported parameter normalizes disabling protections and makes accidental misuse more likely by callers or future integrators. Because this skill uploads documents to an external service, any feature that encourages bypassing safety controls meaningfully raises confidentiality risk.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
print_security_warning()
    
    # 安全检查
    if not skip_security_check:
        is_safe, warnings = check_file_security(file_path)
        if warnings:
            for warning in warnings:
Confidence
84% confidence
Finding
This control-flow branch actually implements the bypass: when `skip_security_check` is true, the script skips the only file vetting before external upload. In a document-conversion skill whose main action is sending local files to `wdangz.com`, this makes the weakness more dangerous because the skipped checks are specifically intended to prevent sensitive or inappropriate file disclosure.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The user-facing natural-language content in the manifest is entirely in Chinese, including the main description and security warnings. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is documented and justified, which is not present here.

Static analysis

No suspicious patterns detected.