Back to skill

Security audit

File Translate

Security checks for vulnerabilities and agentic risk

Overview

The skill is transparent about using 360's translation API, but broad routing plus unsafe redirect and download handling create review-worthy privacy and credential risks.

Install only if you are comfortable sending translated text, images, and whole documents to 360's external service. Use a dedicated low-limit API key, avoid confidential or regulated documents, and prefer a patched version that blocks cross-origin redirects and validates downloaded result URLs before routine use.

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
scripts/translate.py:44
Finding

Bearer API Key May Be Forwarded Across Trust Boundaries During Redirects

Content
View full analysis

Vulnerability Details

File Location: scripts/translate.py:44-51, with authenticated requests originating at scripts/translate.py:92-98, 106-121, 172-180, 202-203, 249-256, and 270-276
Vulnerability Type: Cross-origin credential disclosure through automatic redirects
Risk Level: High

Vulnerable Code

python
def api_request(method, url, headers=None, data=None, json_data=None):
    """Make HTTP request using only stdlib."""
    if headers is None:
        headers = {}
    if json_data is not None:
        data = json.dumps(json_data).encode("utf-8")
        headers.setdefault("Content-Type", "application/json")

    req = urllib.request.Request(url, data=data, headers=headers, method=method)
    try:
        with urllib.request.urlopen(req, timeout=300) as resp:
            body = resp.read().decode("utf-8")
            return json.loads(body) if body else {}

Authenticated callers provide the credential through an ordinary request header:

python
headers = {"Authorization": f"Bearer {api_key}"}
result = api_request(
    "POST",
    f"{API_BASE}/translate",
    headers=headers,
    json_data=payload
)

The direct document-upload path similarly enables default redirect handling:

python
headers = {
    "Authorization": f"Bearer {api_key}",
    "Content-Type": content_type,
}

req = urllib.request.Request(create_url, data=body, headers=headers, method="POST")
try:
    with urllib.request.urlopen(req, timeout=120) as resp:
        upload_result = json.loads(resp.read().decode("utf-8"))

Technical Analysis

urllib.request.urlopen() uses Python's default redirect handler. The implementation does not disable redirects, validate the redirect destination, restrict redirects to the original HTTPS origin, or explicitly remove the Authorization header when the origin changes.

Consequently, an authenticated request that receives a ...[truncated 1658 chars]

Remediation
View remediation

Remediation Suggestions

  1. Disable automatic redirects for every request carrying an authorization credential.
  2. If redirects are operationally required, implement a custom redirect handler that:
    • Allows only https destinations.
    • Allows only an explicit set of trusted 360 API hosts.
    • Rejects redirects that change scheme, hostname, or port.
    • Removes Authorization whenever the origin changes.
    • Enforces a small maximum redirect count.
  3. Keep the API key in an unredirected or otherwise origin-bound header where supported by the HTTP client.
  4. Centralize all authenticated requests in one hardened request function; the direct document-upload requests should not bypass it.
  5. Use a dedicated API key with minimum billing scope, quotas, and usage alerts.
  6. Rotate the API key if execution logs or network telemetry indicate an unexpected redirect.
  7. Add tests asserting that cross-origin redirects are rejected and that credentials are never sent to a redirected host.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/translate.py:316
Finding

Unvalidated API-Supplied Download URLs Permit Client-Side SSRF and Unbounded File Writes

Content
View full analysis

Vulnerability Details

File Location: scripts/translate.py:136-140, 210-224, 287-296, and 316-324
Vulnerability Type: Unvalidated remote URL consumption, client-side SSRF, and missing download limits
Risk Level: Medium

Vulnerable Code

Image translation consumes the first URL supplied by the API:

python
img_url = img_urls[0]

# Download translated image
if out_path:
    download_file(img_url, out_path)
    print(f"Translated image saved to: {out_path}")
else:
    print(f"Translated image URL: {img_url}")

Deep-document translation also trusts a URL selected from response fields:

python
download_url = (
    result.get("download_url")
    or result.get("data", {}).get("download_url")
    or result.get("data", {}).get("output", {}).get("data", {}).get("s3url")
    or result.get("url")
)
pages = result.get("pages") or result.get("data", {}).get("pages") or "?"

if download_url:
    print(f"Done! Pages: {pages}")
    if out_dir:
        os.makedirs(out_dir, exist_ok=True)
        base = os.path.splitext(filename)[0]
        out_file = os.path.join(out_dir, f"{base}_translated.pdf")
        download_file(download_url, out_file)
        print(f"Saved to: {out_file}")

The v1 document path behaves similarly:

python
output = result["data"]["output"]["data"]
s3url = output["s3url"]
pages = output.get("pageCount", "?")
trans_pages = output.get("transPageCount", "?")
print(f"Done! Pages: {pages}, Translated pages: {trans_pages}")

if out_dir:
    os.makedirs(out_dir, exist_ok=True)
    base = os.path.splitext(filename)[0]
    out_file = os.path.join(out_dir, f"{base}_translated.pdf")
    download_file(s3url, out_file)
    print(f"Saved to: {out_file}")

The download function performs no destination validation or response limits:

python
def download_file(url, path):
    """Download a file from URL to local path."""
    r
...[truncated 3087 chars]
Remediation
View remediation

Remediation Suggestions

  1. Require https for every result download.
  2. Maintain an explicit allowlist of documented 360-controlled result and CDN hostnames.
  3. Resolve the destination before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 addresses.
  4. Protect against DNS rebinding by validating the address actually used for the connection, not only an earlier DNS lookup.
  5. Disable redirects or reapply the complete scheme, hostname, port, and resolved-address validation to every redirect hop.
  6. Set a strict maximum redirect count.
  7. Enforce output-size limits using both Content-Length and a running byte counter while streaming.
  8. Validate the response Content-Type and, where practical, verify file signatures for expected image or PDF output.
  9. Download to a temporary file created with restrictive permissions, validate it, and then atomically rename it to the requested destination.
  10. Delete partial files after network, validation, or size-limit failures.
  11. Add tests covering localhost, RFC1918 addresses, IPv6 loopback, cloud metadata addresses, alternate schemes, DNS rebinding, redirect chains, and oversized responses.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (13)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares use of an environment variable and clearly performs network uploads to a third-party API, but it does not define an explicit tool scope such as permissions or allowed-tools. This increases the risk of overbroad execution because the runtime may permit capabilities that are not narrowly constrained or transparently declared to users.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The phrase "or any text" makes the trigger scope much broader than the skill's primary purpose of file and image translation. Overbroad routing can cause the skill to activate for ordinary translation requests and unnecessarily send user content to a third-party service, increasing privacy and cost exposure.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Using the generic trigger term "translate" is overly broad and likely to match many normal user requests that do not require this specific skill. In context, that can unintentionally route sensitive or casual translation content through an external provider, creating unnecessary disclosure and billing risk.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

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.

Content

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

Requires a 360 AI Platform API Key.

  1. Create a key at 360 AI Platform
    (新注册用户会获赠 50 元体验金,可直接用于翻译服务)
  2. Set the environment variable in your shell config:
    bash

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

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.

Content

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

Requires a 360 AI Platform API Key.

  1. Create a key at 360 AI Platform
    (新注册用户会获赠 50 元体验金,可直接用于翻译服务)
  2. Set the environment variable in your shell config:
    bash

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api-reference.md (reported line 15)May include surrounding context.

md
## 1. Text Translation

**POST** `https://api.360.cn/v1/translate`

### Request Body (JSON)

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api-reference.md (reported line 37)May include surrounding context.

md
## 1. Text Translation

**POST** `https://api.360.cn/v1/translate`

### Request Body (JSON)

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api-reference.md (reported line 76)May include surrounding context.

md
## 1. Text Translation

**POST** `https://api.360.cn/v1/translate`

### Request Body (JSON)

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api-reference.md (reported line 92)May include surrounding context.

md
## 1. Text Translation

**POST** `https://api.360.cn/v1/translate`

### Request Body (JSON)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown file documents image and document translation operations that require uploading user-provided images, documents, and text to remote API endpoints. Under the markdown-specific SQP-2 criteria, the description should warn that these operations transmit potentially sensitive user data to an external service, but no such warning is present.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

This skill transmits user-provided text, image, and document content to api.360.cn for translation, which is an external third-party service. In a file-translation skill, that behavior is expected, but it creates a real data-exposure risk if users pass confidential or regulated content without explicit informed consent.

Content

Scanner excerpt · scripts/translate.py (reported line 30)May include surrounding context.

python
import mimetypes
import uuid

API_BASE = "https://api.360.cn/v1"


def get_api_key():

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The deepdoc v2 document workflow uploads entire Word documents to api.360.cn and later downloads translated output from remote URLs, exposing potentially sensitive document contents to an external processor. Given this skill’s purpose, the transmission is functional rather than malicious, but the full-document upload materially increases privacy and compliance risk.

Content

Scanner excerpt · scripts/translate.py (reported line 163)May include surrounding context.

python
def _translate_doc_v2(api_key, file_path, tl, out_dir=None, poll_interval=5, timeout=3600):
    """Word (doc/docx) translation via deepdoc v2 API."""
    DOC_API = "https://api.360.cn/deepdoc/v2/translate"

    filename = os.path.basename(file_path)
    mime = mimetypes.guess_type(file_path)[0] or "application/octet-stream"

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The natural-language examples prominently use --tl zh as the target language in multiple sample commands, which can communicate a default or preferred locale without explaining why. While the code supports arbitrary target languages, the user-facing documentation does not clarify that language choice is up to the user or provide any locale-policy justification.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.