Back to skill

Security audit

Xtranslate

Security checks for vulnerabilities and agentic risk

Overview

This document-translation skill appears functional, but it needs review because it can send document text to cloud providers and leaves sensitive local metadata and temporary files behind.

Install only if you are comfortable with document text being processed by selected cloud providers when cloud mode is used. Prefer local Ollama mode for sensitive files, use an isolated virtual environment, avoid committing generated monitor or summary files, delete tmp conversion files after use, and do not rely on the bundled API-key encryption as strong credential protection.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Warning
Location
src/crypto_utils.py:7
Finding
API Credentials Are Protected with a Public, Deterministic Encryption Key<![CDATA[ ## Vulnerability Details **File Location**: `src/crypto_utils.py:7-31` **Vulnerability Type**: Hardcoded cryptographic secret and insecure credential storage **Risk Level**: Medium ### Vulnerable Code ```python class CryptoUtils: def __init__(self, password="Xtranslate_Secret_Key"): # 生成基于密码的固定密钥(也可以生成一个文件保存,但由于是本地工具,固定算法比较方便) salt = b'xtranslate_salt' kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), length=32, salt=salt, iterations=100000, ) key = base64.urlsafe_b64encode(kdf.derive(password.encode())) self.fernet = Fernet(key) def encrypt(self, text): if not text: return "" return self.fernet.encrypt(text.encode()).decode() def decrypt(self, encrypted_text): if not encrypted_text or not encrypted_text.startswith("gAAAA"): # Fernet 密文特征 return encrypted_text # 如果不是加密文本,直接返回原文(兼容未加密的旧配置) try: return self.fernet.decrypt(encrypted_text.encode()).decode() except: return encrypted_text # 解密失败则返回原样 ``` ### Technical Analysis The application derives its Fernet key from the hardcoded password `Xtranslate_Secret_Key` and the hardcoded salt `xtranslate_salt`. Because both inputs are included in the distributed source code, every installation derives the same encryption key. PBKDF2's iteration count does not provide meaningful protection when the password and salt are already known. Anyone who obtains an encrypted API-key token can reproduce the key derivation process and decrypt the credential. The `decrypt` method also fails open. If a value is not recognized as Fernet ciphertext, or if decryption fails, the method returns the original value and downstream code treats it as a plaintext API key. This behavior can conceal configuration corruption and defeats strict validation of protected credentials. ### Attack Path 1. A user enters an API key through the GUI. ...[truncated 1078 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the hardcoded password and salt from the source code. 2. Store API keys directly in an operating-system credential facility, such as Windows Credential Manager, macOS Keychain, or Linux Secret Service. 3. For headless deployments, use a dedicated secret manager or require credentials to be supplied through a protected runtime environment. 4. If local encryption is unavoidable: - Generate a cryptographically random, unique key for each installation. - Store the key separately from encrypted credentials. - Restrict the key file to the owning user. - Avoid placing the key or encrypted credentials in the project directory. 5. Make decryption fail closed. Invalid ciphertext should raise a specific exception rather than being returned as a possible plaintext key. 6. Do not infer encryption solely from the `gAAAA` prefix. Store explicit format and version metadata. 7. Rotate any API key whose encrypted value may have been exposed, because existing values can be decrypted using the published constants. ]]>

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding
All Third-Party Dependencies Are Installed Without Version or Integrity Pinning<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-11` **Vulnerability Type**: Uncontrolled dependency resolution and supply-chain exposure **Risk Level**: Medium ### Vulnerable Code ```text python-docx pdf2docx openai jieba cryptography customtkinter ollama translate openpyxl python-pptx striprtf ``` The documented installation command is: ```bash pip install -r requirements.txt ``` ### Technical Analysis None of the dependencies has an exact version constraint or an integrity hash. Each installation can therefore resolve to a different set of packages based on the versions available from the configured package index at installation time. This prevents reproducible review and permits dependency behavior to change after the Skill itself has been audited. A compromised upstream release, package-index account takeover, unsafe future release, or incompatible transitive dependency can introduce arbitrary code into the installation. Python packages may execute code during build or installation, and imported packages execute module-level code at runtime. Consequently, dependency compromise can affect the system before document translation begins. The audit did not identify a specific malicious dependency in the repository. The confirmed issue is the absence of controls that bind installation to reviewed artifacts. ### Attack Path 1. A user follows the documented setup procedure and runs `pip install -r requirements.txt`. 2. `pip` resolves the latest matching releases because no exact versions are specified. 3. A dependency or transitive dependency has been compromised, maliciously updated, or replaced through an untrusted package index. 4. The uncontrolled package is downloaded and installed. 5. Malicious code executes during package build, installation, or import. 6. The code runs with the privileges of the user performing installation or invoking the Skill. ### Impact Assessment Successful supply-chain exploitation can execute a ...[truncated 550 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every direct dependency to an exact reviewed version using `package==version`. 2. Generate a lock file that also fixes all transitive dependency versions. 3. Record cryptographic hashes for every accepted distribution and install with `pip --require-hashes`. 4. Prefer binary wheels from trusted sources where appropriate, and review packages that require local builds. 5. Configure installations to use an explicitly trusted package index rather than inheriting arbitrary index settings. 6. Run dependency vulnerability and provenance scanning in continuous integration. 7. Update dependencies through a controlled process that includes security review, compatibility testing, and regenerated hashes. 8. Install the project in an isolated virtual environment under a non-privileged account. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/file_handler.py:55
Finding
PDF Conversion Uses Predictable Temporary Files Without Cleanup<![CDATA[ ## Vulnerability Details **File Location**: `src/file_handler.py:55-64` **Vulnerability Type**: Insecure temporary-file handling and residual sensitive data **Risk Level**: Medium ### Vulnerable Code ```python @staticmethod def pdf_to_docx(pdf_path, tmp_dir): """PDF 转 Word""" file_name = os.path.basename(pdf_path) docx_path = os.path.join(tmp_dir, file_name.replace('.pdf', '.docx')) cv = Converter(pdf_path) cv.convert(docx_path, start=0, end=None) cv.close() return docx_path ``` The converted file is subsequently used without a cleanup operation: ```python if file_ext == '.pdf': if CONFIG.get("VERBOSE_OUTPUT", True): print(f" [PDF -> DOCX] 正在转换以进行分析...") current_work_path = handler.pdf_to_docx(file_path, CONFIG["PDF_TO_DOCX_TMP"]) paragraphs = handler.read_docx(current_work_path) analysis_text = "\n".join(paragraphs[:50]) # 取前50段进行分析 ``` ### Technical Analysis The temporary DOCX path is derived only from the input file's basename and a shared configured directory. It is therefore predictable and not unique. Two PDFs with the same basename produce the same temporary path, even if they originate from different directories. The implementation does not securely create the temporary file, does not enforce restrictive permissions, and does not delete it after processing. This conflicts with the documentation's statement that temporary conversion files are automatically cleaned. Predictable names permit collisions and may allow another local process or user with write access to the temporary directory to pre-create or replace the destination. At minimum, converted copies of sensitive documents remain on disk indefinitely. The exact consequences of link-based replacement depend on operating-system behavior, directory permissions, and how the conversion library opens its destination. Persistent disclosure and basename collision are directly evident from the code. ### Attack Path 1. A user tr ...[truncated 1090 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create a unique temporary directory for each translation with `tempfile.TemporaryDirectory`. 2. Create temporary files through secure operating-system APIs rather than constructing predictable names. 3. Apply owner-only permissions to temporary directories and files where supported. 4. Place conversion and processing in a `try`/`finally` block so cleanup occurs after success, failure, or interruption. 5. Ensure the converter is closed through a context manager or a `finally` block. 6. Reject symbolic links and validate that the final temporary path remains inside the intended temporary directory. 7. Avoid basename-only identifiers; use a random filename or securely generated identifier. 8. Add tests verifying that temporary files are deleted after both successful and failed translations. 9. Update the documentation only after automatic cleanup is actually enforced. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
translation_monitor.py:12
Finding
Translation Monitoring Persists Sensitive File Metadata in Plaintext<![CDATA[ ## Vulnerability Details **File Location**: `translation_monitor.py:12-35,42-57,76-89` **Vulnerability Type**: Plaintext persistence of sensitive path and error metadata **Risk Level**: Low ### Vulnerable Code ```python class TranslationMonitor: def __init__(self, log_file="translation_monitor.json"): self.log_file = Path(log_file) self.records = [] self.load_records() def load_records(self): """加载历史记录""" if self.log_file.exists(): try: with open(self.log_file, 'r', encoding='utf-8') as f: self.records = json.load(f) print(f"[监控] 已加载 {len(self.records)} 条历史记录") except Exception as e: print(f"[监控] 加载记录失败: {e}") self.records = [] else: print("[监控] 创建新的监控记录文件") def save_records(self): """保存记录到文件""" try: with open(self.log_file, 'w', encoding='utf-8') as f: json.dump(self.records, f, ensure_ascii=False, indent=2) except Exception as e: print(f"[监控] 保存记录失败: {e}") def start_translation(self, file_path, engine, target_lang): """开始翻译时记录""" record = { "id": len(self.records) + 1, "timestamp": datetime.now().isoformat(), "file_path": str(file_path), "engine": engine, "target_lang": target_lang, "status": "started", "start_time": time.time(), "phases": {} } return record ``` ```python def finish_translation(self, record, success=True, result_stats=None, error_msg=None): """完成翻译记录""" record["end_time"] = time.time() record["duration"] = record["end_time"] - record["start_time"] record["status"] = "completed" if success else "failed" record["success"] = success if result_stats: record["result_stats"] = result_stats ...[truncated 2316 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make persistent monitoring opt-in and clearly disclose what metadata is stored. 2. Store only the minimum required information: - Replace complete paths with basenames, random record identifiers, or keyed hashes. - Avoid storing output paths unless operationally necessary. - Sanitize exception messages before persistence. 3. Add configurable retention limits and automatically remove old records. 4. Store logs in an appropriate per-user application-data directory rather than the project working directory. 5. Create monitoring files with owner-only permissions where the platform permits. 6. Add `translation_monitor.json` and generated summary files to `.gitignore`. 7. Provide a command or interface control to delete monitoring history. 8. Use atomic file replacement and consider encryption backed by an operating-system secret store if sensitive metadata must be retained. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (62)

Credential Access

High
Category
Privilege Escalation
Content
*.log

# Environment files
.env
.env.*
!.env.example
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Missing User Warnings

High
Confidence
98% confidence
Finding
The skill promotes cloud translation engines but does not clearly warn that document contents will be transmitted to third-party model providers. Because the tool handles potentially sensitive PDFs, Word, Excel, and PPT files, lack of upfront disclosure can lead to unintended exfiltration of confidential content outside the local environment.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill advertises capabilities that read files, write outputs, and use environment-provided API keys, but it does not declare an explicit tool scope or permission boundary. That increases the chance the agent will invoke file and secret-adjacent operations without clear user-visible constraints, especially in environments where skill permissions are expected to gate access.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The invocation phrases are broad enough to match ordinary translation requests, so the skill may be triggered when a user only wanted simple text translation rather than file processing. In context, this matters because invocation can cause local file access and possible cloud upload of document contents, making accidental activation more harmful than a harmless routing mistake.

Natural-Language Policy Violations

Medium
Confidence
86% confidence
Finding
The skill appears to automatically apply Chinese-specific formatting and keyword extraction behaviors without explicit user consent. In context this can alter document meaning, styling, or compatibility unexpectedly, and keyword extraction itself may process sensitive content beyond what users expect from a straightforward translation task.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill describes smart monitoring and process recording without warning users that translation activity and document-related metadata may be logged. Even if full document bodies are not always stored, operational records about filenames, timing, languages, models, and excerpts can expose sensitive business or personal information.

Ssd 3

Medium
Confidence
95% confidence
Finding
The monitoring instructions say every translation is fully recorded, creating a data retention risk for user-provided document contents or content-derived metadata. In a document-translation skill, the context makes this especially sensitive because inputs may contain contracts, financial data, legal text, or personal information.

Ssd 3

Medium
Confidence
97% confidence
Finding
The skill explicitly states that all translation records are stored in a persistent JSON file, which creates an ongoing local data exposure risk. Persistent logs are easy to copy, inspect, back up, or leak, and they may reveal sensitive document names, processing details, and potentially excerpts or analysis artifacts over time.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This Python file contains natural-language docstrings and all user-facing print output exclusively in Chinese, including the title, status messages, and recommendations. Under the policy rules, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly justified, which is not present here.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This file contains natural-language instructions and examples exclusively in Chinese, which can amount to forcing a specific language on users without opt-in. The policy allows locale constraints only when user choice is offered or the restriction is clearly documented and justified, neither of which appears here.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The entire markdown file presents the skill content exclusively in Chinese, including the title, section headings, comments, and explanatory bullets. Under the policy rule, forcing a specific language without an explicit user choice or documented justification is a natural-language policy violation.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Content
def check_package(package_name):
    """检查单个包是否已安装"""
    try:
        __import__(package_name)
        return True
    except ImportError:
        return False
Confidence
75% confidence
Finding
Dynamic __import__() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The string literal on L30 hard-codes the generated context prompt in English ('The text contains...' / 'Please ensure...'). This imposes a specific language on downstream behavior without user opt-in, which matches the language/locale policy violation criteria.

Vague Triggers

Medium
Confidence
80% confidence
Finding
This plain-text config sets TARGET_LANG=zh-CN as a global default, but the file provides no surrounding activation context or constraints explaining when this locale-specific behavior should apply. In a broadly applicable translation skill, a fixed default target language can overlap with many general translation requests and is not narrowed by explicit scope or negative examples.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The natural-language configuration sets TARGET_LANG=zh-CN, which imposes a specific locale by default. There is no indication in this file that users are offered a language choice or have explicitly opted into Chinese output, making it a language-policy concern.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The configuration includes multiple cloud translation endpoints but provides no in-file indication that translated content may be transmitted to third-party services. If users process sensitive documents, they may unknowingly send proprietary or personal data off-host, creating confidentiality and compliance risk.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The top-level documentation describes this module as a configuration loader that reads from config.txt, which implies read-oriented behavior. However, importing the module triggers os.makedirs on the output and temporary directories at L132-L136, introducing filesystem-modifying side effects not reflected by the docstring.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The configuration hard-codes a default target locale of "zh-CN", which forces a specific language/locale choice unless the user overrides it. This is a natural-language policy issue because the file does not indicate user choice, opt-in, or a documented region-specific justification for the default locale.

External Transmission

Medium
Category
Data Exfiltration
Content
"env_key": raw_config.get("CLOUD_MODEL_DEEPSEEK_ENV_KEY", "DEEPSEEK_API_KEY")
            },
            "GPT-4o": {
                "base_url": raw_config.get("CLOUD_MODEL_GPT4O_BASE_URL", "https://api.openai.com/v1"),
                "model": raw_config.get("CLOUD_MODEL_GPT4O_MODEL", "gpt-4o"),
                "env_key": raw_config.get("CLOUD_MODEL_GPT4O_ENV_KEY", "OPENAI_API_KEY")
            },
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
"env_key": raw_config.get("CLOUD_MODEL_DEEPSEEK_ENV_KEY", "DEEPSEEK_API_KEY")
            },
            "GPT-4o": {
                "base_url": raw_config.get("CLOUD_MODEL_GPT4O_BASE_URL", "https://api.openai.com/v1"),
                "model": raw_config.get("CLOUD_MODEL_GPT4O_MODEL", "gpt-4o"),
                "env_key": raw_config.get("CLOUD_MODEL_GPT4O_ENV_KEY", "OPENAI_API_KEY")
            },
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
"env_key": raw_config.get("CLOUD_MODEL_GPT4O_ENV_KEY", "OPENAI_API_KEY")
            },
            "Claude 3.5 Sonnet": {
                "base_url": raw_config.get("CLOUD_MODEL_CLAUDE_BASE_URL", "https://api.anthropic.com/v1"),
                "model": raw_config.get("CLOUD_MODEL_CLAUDE_MODEL", "claude-3-5-sonnet-20240620"),
                "env_key": raw_config.get("CLOUD_MODEL_CLAUDE_ENV_KEY", "ANTHROPIC_API_KEY")
            },
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
"env_key": raw_config.get("CLOUD_MODEL_GPT4O_ENV_KEY", "OPENAI_API_KEY")
            },
            "Claude 3.5 Sonnet": {
                "base_url": raw_config.get("CLOUD_MODEL_CLAUDE_BASE_URL", "https://api.anthropic.com/v1"),
                "model": raw_config.get("CLOUD_MODEL_CLAUDE_MODEL", "claude-3-5-sonnet-20240620"),
                "env_key": raw_config.get("CLOUD_MODEL_CLAUDE_ENV_KEY", "ANTHROPIC_API_KEY")
            },
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
"env_key": raw_config.get("CLOUD_MODEL_CLAUDE_ENV_KEY", "ANTHROPIC_API_KEY")
            },
            "SiliconFlow (Qwen2.5)": {
                "base_url": raw_config.get("CLOUD_MODEL_SILICONFLOW_BASE_URL", "https://api.siliconflow.cn/v1"),
                "model": raw_config.get("CLOUD_MODEL_SILICONFLOW_MODEL", "deepseek-ai/DeepSeek-V3"),
                "env_key": raw_config.get("CLOUD_MODEL_SILICONFLOW_ENV_KEY", "SILICONFLOW_API_KEY")
            },
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
"env_key": raw_config.get("CLOUD_MODEL_CLAUDE_ENV_KEY", "ANTHROPIC_API_KEY")
            },
            "SiliconFlow (Qwen2.5)": {
                "base_url": raw_config.get("CLOUD_MODEL_SILICONFLOW_BASE_URL", "https://api.siliconflow.cn/v1"),
                "model": raw_config.get("CLOUD_MODEL_SILICONFLOW_MODEL", "deepseek-ai/DeepSeek-V3"),
                "env_key": raw_config.get("CLOUD_MODEL_SILICONFLOW_ENV_KEY", "SILICONFLOW_API_KEY")
            },
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This code file performs file-system writes by creating the configured output and temporary directories as soon as the module is imported. Although there are comments, they are implementation notes rather than user-facing warnings, and there is no confirmation, logging, or explicit disclosure that importing the skill will modify the local filesystem.

Static analysis

No suspicious patterns detected.