Back to skill

Security audit

Encrypted File Writer

Security checks for vulnerabilities and agentic risk

Overview

This is a local file-writing tool, but its spreadsheet append mode can destroy existing data and its naming/docs can mislead users about encryption and format support.

Install only if you need a simple local writer and can tolerate its limitations. Do not assume it encrypts files. Back up important files before using overwrite or append, avoid XLSX append on existing workbooks, and do not append to untrusted DOCX files.

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

Error
Location
write_file.py:367
Finding
XLSX Append Operation Silently Overwrites Existing Spreadsheet Data<![CDATA[ ## Vulnerability Details **File Location**: `write_file.py:367-402` **Vulnerability Type**: Destructive append implementation and data integrity failure **Risk Level**: High ### Vulnerable Code ```python def append_to_xlsx(file_path, rows): """ 追加数据到 Excel 文件(简化实现:读取现有数据,合并后重新创建) Args: file_path: 文件路径 rows: 二维数组,每行数据 Returns: 写入的字节数 """ # 读取现有数据 existing_rows = [] with zipfile.ZipFile(file_path, 'r') as zf: try: shared_strings_content = zf.read('xl/sharedStrings.xml').decode('utf-8') # 提取所有字符串 import re matches = re.findall(r'<t>([^<]*)</t>', shared_strings_content) # 读取 worksheet 获取行列结构 worksheet_content = zf.read('xl/worksheets/sheet1.xml').decode('utf-8') # 简单解析:获取行数 row_matches = re.findall(r'<row r="(\d+)"', worksheet_content) if row_matches: max_row = int(max(row_matches)) # 这里简化处理,假设每行有相同列数 # 实际应该更复杂地解析 else: max_row = 0 except: pass # 合并数据并重新创建 all_rows = existing_rows + rows return create_xlsx(file_path, all_rows if all_rows else rows) ``` ### Technical Analysis The function claims to append rows to an existing XLSX workbook, but `existing_rows` is initialized as an empty list and is never populated. Although the implementation reads `xl/sharedStrings.xml` and `xl/worksheets/sheet1.xml`, the extracted strings, row references, and maximum row number are not converted into existing spreadsheet rows. Consequently, the following expression always contains only the newly supplied rows: ```python all_rows = existing_rows + rows ``` The function then calls `create_xlsx()` with the original file path. That function opens the destination in binary overwrite mode and creates a new minimal workbook. Existing cells, worksheets, formulas, styles, ...[truncated 1753 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the simplified regular-expression parsing with a proven XLSX/OpenXML library such as `openpyxl`, if introducing a maintained dependency is acceptable. 2. If standard-library-only operation is required, fully parse: - Shared strings. - Inline strings. - Worksheet cell references and types. - Sparse rows and columns. - XML entities and namespaces. 3. Populate `existing_rows` before combining it with new rows. 4. Preserve all unrelated ZIP members rather than creating a new minimal workbook. 5. Do not use a bare `except:`. Catch expected exceptions explicitly and abort without modifying the original file when parsing fails. 6. Write the updated workbook to a temporary file in the destination directory. 7. Validate the completed temporary workbook, flush it to disk, and atomically replace the original only after success. 8. Retain or create a backup when destructive replacement cannot be made atomic. 9. Add regression tests verifying that: - Existing rows remain unchanged. - New rows appear after existing rows. - Styles, formulas, worksheets, and metadata are preserved. - Malformed workbooks produce an error without changing the original file. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
write_file.py:231
Finding
Unbounded DOCX Archive Decompression Enables Memory Exhaustion<![CDATA[ ## Vulnerability Details **File Location**: `write_file.py:231-245` **Vulnerability Type**: Unbounded ZIP decompression and memory consumption **Risk Level**: Medium ### Vulnerable Code ```python def append_to_docx(file_path, text_lines): """ 追加内容到 Word 文档 Args: file_path: 文件路径 text_lines: 文本行列表 Returns: 写入的字节数 """ # 读取现有文档 with zipfile.ZipFile(file_path, 'r') as zf: # 读取所有文件 files = {item.filename: zf.read(item.filename) for item in zf.infolist()} ``` ### Technical Analysis DOCX files are ZIP archives. When appending content, the function enumerates every archive member, decompresses each member completely, and retains all decompressed contents in a dictionary. The implementation imposes no limits on: - The number of ZIP members. - The uncompressed size of an individual member. - The cumulative uncompressed archive size. - The compressed-to-uncompressed size ratio. - Duplicate member names. - Available process memory. A small malicious DOCX can therefore contain highly compressed members that expand to a very large size. Calling `zf.read()` for every entry may consume all available memory before the document is modified. The reviewed code does not extract archive entries to filesystem paths, so no ZIP path-traversal vulnerability was identified in this flow. The confirmed issue is resource exhaustion caused by unbounded in-memory decompression. ### Attack Path 1. An attacker creates a DOCX-compatible ZIP archive containing one or more highly compressed, extremely large members. 2. The crafted document is placed at a path the Agent can access, or the user is persuaded to append text to it. 3. The Skill invokes `append_to_docx()`. 4. `zf.infolist()` enumerates every archive member. 5. `zf.read(item.filename)` decompresses each member without checking its declared or actual expanded size. 6. All expanded member contents are retained simultaneously in the `files` dict ...[truncated 833 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Inspect each `ZipInfo` entry before decompression. 2. Establish strict configurable limits for: - Maximum number of members. - Maximum uncompressed size per member. - Maximum cumulative uncompressed size. - Maximum compression ratio. 3. Reject suspicious entries before calling `read()`. 4. Read only the entries required for modification where possible, especially `word/document.xml`. 5. Stream or copy unaffected members instead of retaining the entire expanded archive in memory. 6. Reject duplicate member names and malformed archive structures. 7. Catch `BadZipFile`, decompression errors, and size-limit violations explicitly. 8. Write the modified archive to a temporary file and atomically replace the original only after successful validation. 9. Run the operation under process-level memory and execution-time limits as defense in depth. 10. Add tests using high-compression-ratio and oversized archives to verify safe rejection without modifying the original file. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill’s branding and documentation materially overstate its security and format capabilities: the name suggests encryption, the description suggests enterprise-security robustness, and the text claims 80+ supported formats, while the documented behavior only truly handles text-like files plus limited .docx/.xlsx generation. This mismatch can cause operators or downstream agents to trust the tool for secure handling of sensitive files or format-correct writes when it does not actually provide encryption or broad format-aware protections, leading to misuse and accidental exposure or corruption.

Credential Access

High
Category
Privilege Escalation
Content
|------|--------|----------|
| **文本类** | .txt, .md, .markdown, .rst, .log, .csv, .tsv | UTF-8 文本写入 |
| **代码类** | .java, .py, .js, .ts, .jsx, .tsx, .c, .cpp, .h, .cs, .go, .rs, .rb, .php, .vue | UTF-8 文本写入 |
| **配置类** | .json, .xml, .yaml, .yml, .toml, .ini, .cfg, .properties, .gradle, .config, .env | UTF-8 文本写入 |
| **样式类** | .html, .htm, .css, .scss, .sass, .less | UTF-8 文本写入 |
| **脚本类** | .sh, .bash, .bat, .cmd, .ps1, .sql | UTF-8 文本写入 |
| **Office** | .docx (Word), .xlsx (Excel) | OpenXML ZIP 格式写入 |
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
'.sql', '.graphql', '.gql',
    
    # 配置文件
    '.config', '.env', '.env.example', '.env.local', '.env.production',
    '.htaccess', '.editorconfig', '.gitignore', '.gitattributes', '.gitmodules',
    '.dockerfile', '.dockerignore',
    '.makefile', '.mk', '.cmake',
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
'.sql', '.graphql', '.gql',
    
    # 配置文件
    '.config', '.env', '.env.example', '.env.local', '.env.production',
    '.htaccess', '.editorconfig', '.gitignore', '.gitattributes', '.gitmodules',
    '.dockerfile', '.dockerignore',
    '.makefile', '.mk', '.cmake',
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
'.sql', '.graphql', '.gql',
    
    # 配置文件
    '.config', '.env', '.env.example', '.env.local', '.env.production',
    '.htaccess', '.editorconfig', '.gitignore', '.gitattributes', '.gitmodules',
    '.dockerfile', '.dockerignore',
    '.makefile', '.mk', '.cmake',
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
This markdown file contains user-facing natural-language content exclusively in Chinese, including headings, descriptions, and remediation notes. Under the policy rule for language/locale violations, forcing a specific language without user opt-in or a documented justification is a finding.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The README documents overwrite-by-default behavior and automatic directory creation without prominently warning about destructive outcomes. In a file-writing skill, this increases the risk of accidental data loss or unintended modification of local files, especially when invoked by an agent or with user-supplied paths.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest description says the skill supports text, Word (.docx), Excel (.xlsx), and 80+ formats. However, the README explicitly says direct writing to .docx/.xlsx is not supported without extra dependencies, and the documented usage is a CLI text file writer using encodings rather than a true multi-format document writer. This is a clear mismatch between claimed scope and described behavior.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The manifest description and nearly all user-facing instructions are presented exclusively in Chinese, with no indication that users may choose another language. Under the policy, forcing a specific language without opt-in is a natural-language locale violation unless the constraint is clearly justified as region-specific.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The metadata is internally inconsistent: the skill name/description still present it as an 'encrypted' file writer while the changelog claims that misleading encryption language was removed. In a security-sensitive enterprise context, this can mislead users into believing written files are protected by encryption when they may only be encoded or formatted, causing inappropriate handling of sensitive data.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The description text is entirely in Chinese, which indicates a language-specific skill presentation without offering a user language choice or explaining that the skill is intended only for a Chinese-speaking or region-specific context. This matches the policy concern for natural-language locale constraints that are not opt-in or clearly justified.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This Python file contains natural-language documentation entirely in Chinese, including the tool name, usage, and warnings, and the CLI help/output strings are also Chinese-only. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly justified, which it is not here.

Intent-Code Divergence

Low
Confidence
87% confidence
Finding
The skill is named 'encrypted-file-writer' in the manifest, and the README title presents it as an enterprise file writer, but the documentation then explicitly states '本工具不是加密工具'. This creates an intent-level contradiction between the apparent skill identity and the documented behavior, which could mislead users about security properties.

Natural-Language Policy Violations

Low
Confidence
77% confidence
Finding
Natural-language policy violations include forcing a specific language or locale without user opt-in. This README presents all operational guidance in Chinese and does not indicate that users can choose another language or that the locale restriction is required for a region-specific purpose.

Static analysis

No suspicious patterns detected.