Back to skill

Security audit

Chanjing Text To Digital Person

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but it handles API secrets and downloads files with weaker runtime scoping than its manifest implies.

Review before installing. Use only trusted environment variables, avoid setting CHANJING_OPENAPI_BASE_URL or CHANJING_API_BASE outside controlled testing, protect ~/.chanjing/credentials.json with restrictive permissions, and only run downloads for trusted result URLs into a dedicated output directory.

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

Error
Location
scripts/_auth.py:20
Finding

Unvalidated API Base URL Can Exfiltrate Chanjing Credentials and Access Tokens

Content
View full analysis
str: return ( os.environ.get("CHANJING_OPENAPI_BASE_URL") or os.environ.get("CHANJING_API_BASE") or _DEFAULT_OPENAPI_BASE ).rstrip("/") ``` ```python # scripts/_auth.py:93-101 url = API_BASE + "/open/v1/access_token" req = urllib.request.Request( url, data=json.dumps({"app_id": app_id, "secret_key": secret_key}).encode("utf-8"), headers={"Content-Type": "application/json"}, method="POST", ) try: with urllib.request.urlopen(req, timeout=30) as resp: ``` ```python # scripts/_task_api.py:6 API_BASE = (__import__("os").environ.get("CHANJING_OPENAPI_BASE_URL") or __import__("os").environ.get("CHANJING_API_BASE") or "https://open-api.chanjing.cc").rstrip("/") ``` ```python # scripts/_task_api.py:21-45 def api_get(token, path, query=None): query = query or {} suffix = "" if query: suffix = "?" + urllib.parse.urlencode(query) req = urllib.request.Request( f"{API_BASE}{path}{suffix}", headers={"access_token": token}, method="GET", ) with urllib.request.urlopen(req, timeout=30) as resp: body = json.loads(resp.read().decode("utf-8")) if body.get("code") != 0: raise RuntimeError(body.get("msg", body)) return body.get("data") def api_post(token, path, payload): req = urllib.request.Request( f"{API_BASE}{path}", data=json.dumps(payload).encode("utf-8"), headers={"access_token": token, "Content-Type": "application/json"}, method="POST", ) with urllib.request.urlopen(req, timeout=30) as resp: ``` ### Technical Analysis The API base URL is taken directly from either `CHANJING_OPENAPI_BASE_URL ...[truncated 1936 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/_auth.py:67
Finding

Credential File Is Persisted Without Explicit Restrictive Permissions

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/download_result.py:39
Finding

Downloader Allows Arbitrary Network Requests and Arbitrary Writable File Overwrites

Content
View full analysis
Remediation
View remediation
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 (33)

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

The skill declares use of credentials.json containing app_id/secret_key and persistence of access_token on disk, which confirms handling of sensitive secrets with local storage. Persistent credential material on disk increases exposure to accidental leakage, overbroad file access by other tools, or theft from a compromised host.

Content

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

md
description: >-
  Use Chanjing text-to-digital-person APIs for AI portraits, talking videos,
  optional LoRA training, polling, and explicit downloads when requested.
credential: credentials.json (app_id/secret_key; access_token persisted on disk)
openclaw_primary_env: false
environment: CHANJING_OPENAPI_CREDENTIALS_DIR, CHANJING_OPENAPI_BASE_URL
legacy_environment: CHANJING_CONFIG_DIR, CHANJING_API_BASE

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

This section states the skill shares ~/.chanjing/credentials.json and may automatically open a login page or execute a helper script when credentials are missing. Auto-launching browser flows or helper subprocesses in response to missing credentials increases the attack surface and can surprise users, especially if path integrity or target URL validation is weak.

Content

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

md
本 Skill 与 guard 共用:

* `~/.chanjing/credentials.json`
* `https://open-api.chanjing.cc`

无凭证时,脚本会自动打开蝉镜登录页(若同仓库存在则执行 **`chanjing-credentials-guard/scripts/open_login_page.py`**,否则 **`webbrowser.open`**),并提示本地执行 **`chanjing_config.py`**。

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

The documentation says _auth.py reads credentials.json and writes back access_token/expire_in, confirming local mutation of sensitive auth state by the skill. Writing refreshed tokens to disk can create persistence and exfiltration risks if logs, backups, or other processes can access the file.

Content

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

md
| 文件名(仓库内) | 说明 |
|------------------|------|
| `_auth.py` | 读 **`credentials.json`**、刷新并 **写回** **`access_token` / `expire_in`**;缺 AK/SK 时尝试 **`open_login_page.py`** |
| `_task_api.py` | 任务 API 共用逻辑(由各 CLI import) |
| `create_photo_task.py` | 创建文生图任务 → `photo_unique_id` |
| `get_photo_task.py` | 单个文生图任务详情 |

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

The manifest explicitly enables persistent storage of access tokens on disk in credentials.json. This creates a real exposure path if the workspace, home directory, backups, or other local processes can read the file, and it is more concerning here because the token is an active API credential rather than a static non-sensitive cache item.

Content

Scanner excerpt · manifest.yaml (reported line 65)May include surrounding context.

yaml
persistAccessTokenOnDisk: true
  primaryEnvIntentionallyOmitted: true
  doNotCommitToVcs:
    - credentials.json

clientPermissions:
  network:

Credential Access

High
Category
Privilege Escalation
Confidence
80% confidence
Finding

Granting write access to the credentials.json file is riskier than mere read access because it allows modification or replacement of stored credentials and tokens. In combination with persistent token storage, this can enable tampering, credential poisoning, or unintended long-term retention of secrets on disk.

Content

Scanner excerpt · manifest.yaml (reported line 76)May include surrounding context.

yaml
read:
      - "${CHANJING_OPENAPI_CREDENTIALS_DIR or CHANJING_CONFIG_DIR or ~/.chanjing}/credentials.json"
    write:
      - "${CHANJING_OPENAPI_CREDENTIALS_DIR or CHANJING_CONFIG_DIR or ~/.chanjing}/credentials.json"
  browser:
    mayOpenForAuth: true
    documentedHosts:

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · manifest.yaml (reported line 47)May include surrounding context.

yaml
#!/usr/bin/env python3
# 鉴权:与 chanjing-credentials-guard 使用同一配置文件(CONFIG_DIR/credentials.json)
# 无 AK/SK 时执行 open_login_page.py 打开注册/登录页
import json
import os

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · manifest.yaml (reported line 54)May include surrounding context.

yaml
#!/usr/bin/env python3
# 鉴权:与 chanjing-credentials-guard 使用同一配置文件(CONFIG_DIR/credentials.json)
# 无 AK/SK 时执行 open_login_page.py 打开注册/登录页
import json
import os

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · manifest.yaml (reported line 56)May include surrounding context.

yaml
#!/usr/bin/env python3
# 鉴权:与 chanjing-credentials-guard 使用同一配置文件(CONFIG_DIR/credentials.json)
# 无 AK/SK 时执行 open_login_page.py 打开注册/登录页
import json
import os

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · manifest.yaml (reported line 74)May include surrounding context.

yaml
#!/usr/bin/env python3
# 鉴权:与 chanjing-credentials-guard 使用同一配置文件(CONFIG_DIR/credentials.json)
# 无 AK/SK 时执行 open_login_page.py 打开注册/登录页
import json
import os

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/_auth.py (reported line 2)May include surrounding context.

python
#!/usr/bin/env python3
# 鉴权:与 chanjing-credentials-guard 使用同一配置文件(CONFIG_DIR/credentials.json)
# 无 AK/SK 时执行 open_login_page.py 打开注册/登录页
import json
import os

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/_auth.py (reported line 29)May include surrounding context.

python
#!/usr/bin/env python3
# 鉴权:与 chanjing-credentials-guard 使用同一配置文件(CONFIG_DIR/credentials.json)
# 无 AK/SK 时执行 open_login_page.py 打开注册/登录页
import json
import os

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown file presents the operational instructions and safety-relevant usage guidance almost entirely in Chinese, which effectively imposes a specific language on users. The policy allows locale constraints only when users are given a choice or the constraint is clearly documented and justified, neither of which appears here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

SQP-3 applies to natural-language policy violations across all file types, including markdown. The trigger section lists activation phrases exclusively in Chinese and does not indicate that other languages are supported, optional, or intentionally restricted for a region-specific skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest explicitly states that access tokens are persisted to disk, but the user-facing summary does not warn about this credential-handling behavior. Persisting bearer tokens increases the chance of credential theft from the local filesystem, especially because the same manifest also grants read/write access to the credential store.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest allows downloading content from API response URLs into the user's environment without making that behavior obvious in the skill summary. Downloading remote content can introduce untrusted files into the workspace and may expose users to malicious or unexpected payloads if the API or response URLs are compromised.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The reference documents a download_result.py script that downloads output_url to the local filesystem, but it does not warn users that invoking it causes a local file write. In an agent skill, undisclosed filesystem side effects reduce informed consent and can lead to overwriting files, storing untrusted remote content locally, or unexpectedly persisting sensitive/generated media on the host.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/_auth.py (reported line 46)May include surrounding context.

python
skills_dir = Path(__file__).resolve().parent.parent.parent
        script = skills_dir / "chanjing-credentials-guard" / "scripts" / "open_login_page.py"
        if script.exists():
            subprocess.run([sys.executable, str(script)], check=False, timeout=5)
        else:
            import webbrowser

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code writes app credentials and access tokens into a JSON file under the user's home/config directory without setting restrictive file permissions or using a secure credential store. If the host is shared or local files are exposed by other software, these secrets can be read and reused to access the remote API.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The code sends app_id and secret_key to a remote API endpoint to obtain an access token. Although this is functionally expected for authentication, this file does not provide an explicit warning or disclosure to the user that local credentials will be transmitted over the network.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/_task_api.py (reported line 6)May include surrounding context.

python
import urllib.parse
import urllib.request

API_BASE = (__import__("os").environ.get("CHANJING_OPENAPI_BASE_URL") or __import__("os").environ.get("CHANJING_API_BASE") or "https://open-api.chanjing.cc").rstrip("/")

PHOTO_RUNNING = {"Ready", "Generating", "Queued"}
PHOTO_SUCCESS = {"Success"}

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The natural-language docstring and CLI descriptions are presented entirely in Chinese, including usage and output descriptions, with no indication that users may choose another language or that the tool is intended only for a Chinese-speaking context. Under the stated policy, forcing a specific language without opt-in is a locale-policy concern.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

This code constructs a request body from user-provided attributes and transmits it to a remote API via api_post. While the script's purpose is to create a photo-generation task, the file does not include any explicit user-facing warning, comment, or docstring disclosure that the supplied prompts and reference image URL will be sent to an external service.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This Python file contains natural-language docstrings, argument descriptions, and error messages exclusively in Chinese. Because the skill does not provide an opt-in language choice or state that it is intentionally limited to a Chinese-speaking or region-specific context, it may violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The docstring, argparse description/help text, and runtime messages are all hard-coded in Chinese, which imposes a specific language on users. Under the policy, locale constraints should either be optional via user choice or clearly documented as justified for a region-specific tool; neither is present in this file.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.