Back to skill

Security audit

Chanjing One Click Video Creation

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its video-generation purpose, but its credentialed network handling is broader than its declared trust boundary and deserves review before installation.

Install only if you are comfortable giving this skill access to your Chanjing API credentials and local media tooling. Keep credentials.json out of version control with 0600-style permissions, avoid running it in untrusted shared or CI environments, pin the API base to the official Chanjing host, and prefer a patched version that validates authenticated hosts and bounds media downloads.

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/run_render.py:27
Finding

Access Token Disclosure Through an Unrestricted API Base URL Override

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 def fetch_audio_task_state(token: str, task_id: str) -> dict[str, Any]: url = f"{API_BASE}/open/v1/audio_task_state" body = json.dumps({"task_id": task_id}).encode("utf-8") req = urllib.request.Request( url, data=body, headers={"access_token": token, "Content-Type": "application/json"}, method="POST", ) with urllib.request.urlopen(req, timeout=60) as resp: return json.loads(resp.read().decode("utf-8")) ``` ### Technical Analysis The API base URL is obtained from `CHANJING_OPENAPI_BASE_URL` or the legacy `CHANJING_API_BASE` environment variable without validating its scheme, hostname, port, or origin. The renderer subsequently obtains a legitimate Chanjing access token from the sibling authentication module and places that token in the `access_token` HTTP header. Consequently, a process that can influence the renderer's environment can redirect the authenticated request to an attacker-controlled server. The code does not require HTTPS, restrict the destination to `open-api.chanjing.cc`, or prevent an allowed endpoint from redirecting the request to another origin. This implementation is also inconsistent with the intended network boundary in `manifest.yaml`, which declares an allowlist containing `open-api.chanjing.cc`. The code itself does not enforce that boundary. The credential lookup is necessary for the declared video-generation workflow. The ability to send the resulting token to any environment-selected origin is not necessary and exceeds the mini ...[truncated 1451 chars]
Remediation
View remediation
str: raw = ( os.environ.get("CHANJING_OPENAPI_BASE_URL") or os.environ.get("CHANJING_API_BASE") or _DEFAULT_OPENAPI_BASE ).rstrip("/") parsed = urlsplit(raw) if ( parsed.scheme != "https" or parsed.hostname not in _ALLOWED_API_HOSTS or parsed.username is not None or parsed.password is not None or parsed.port not in (None, 443) ): raise ValueError("Untrusted Chanjing API endpoint") return raw ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/run_render.py:258
Finding

Unvalidated API-Returned Media Downloads Permit SSRF and Resource Exhaustion

Content
View full analysis
None: with DOWNLOAD_SEM: req = urllib.request.Request(url, method="GET") with urllib.request.urlopen(req, timeout=300) as resp: dest.write_bytes(resp.read()) ``` The TTS response URL is consumed directly: ```python full = data.get("full") or {} url = full.get("url") if not url: raise RuntimeError("TTS 完成但无 full.url") raw = work / f"tts_batch_{bi}.mp3" download_url(url, raw) ``` Digital-human and AI polling results are also consumed directly: ```python u0 = with_retry(lambda: poll_compose(root, vid0), retries) url_dh[first_dh_sid] = u0 result["render_result"]["scene_video_urls"][f"dh_{first_dh_sid}"] = u0 p0 = work / f"scene{first_dh_sid:02d}_dh_raw.mp4" download_url(u0, p0) ``` ```python for sid, u in sorted(url_dh.items()): if sid in dh_files: continue p = work / f"scene{sid:02d}_dh_raw.mp4" download_url(u, p) dh_files[sid] = p ``` ```python for (sid, k), u in sorted(url_ai.items()): p = work / f"scene{sid:02d}_ai_part{k}.mp4" download_url(u, p) ai_files[(sid, k)] = p ``` ### Technical Analysis Media locations returned by the TTS API and sibling polling scripts are passed directly to `urllib.request.urlopen`. The downloader does not enforce HTTPS, restrict destinations to an approved Chanjing CDN hostname, reject local or private-network destinations, or validate redir ...[truncated 2837 chars]
Remediation
View remediation
None: parsed = urlsplit(url) if parsed.scheme != "https" or parsed.hostname not in _ALLOWED_MEDIA_HOSTS: raise ValueError("Untrusted media URL") total = 0 temporary = dest.with_suffix(dest.suffix + ".part") try: with DOWNLOAD_SEM: req = urllib.request.Request(url, method="GET") with urllib.request.urlopen(req, timeout=300) as resp: with temporary.open("wb") as output: while True: chunk = resp.rea ...[truncated 431 chars]
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (36)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

声明描述的是一个完整的短视频自动生成技能,核心能力应是根据输入生成视频成片及相关内容。而实际代码块只是 tests/test_id_resolver.py 的测试/辅助逻辑:读取测试默认配置、解析 audio_man/person_id/figure_type,并在缺失时调用 list_voices 与 list_figures 查询 ID。它明确注明不在生产路径 run_render.py 中使用,不读写缓存,也不执行视频生成。虽然它确实会调用同仓库脚本,并可能间接访问 Chanjing 相关接口,但这只是为单元测试准备 ID,和声明的主要用途存在明显不一致,因此应判定为描述与行为不匹配。

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The skill explicitly relies on a credentials.json containing app_id/secret_key and persists access tokens on disk. Storing long-lived secrets and refreshed tokens locally increases the blast radius of filesystem compromise, accidental disclosure, or overly broad agent access, especially because the skill also performs network calls and subprocess execution.

Content

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

md
description: >-
  用户输入选题或工作流,自动生成完整短视频成片(文案、分镜、数字人口播与
  AI 画面混剪);调用 Chanjing Open API 与同仓库子技能脚本。
credential: credentials.json (app_id/secret_key; access_token persisted on disk)
openclaw_primary_env: false
machine_readable: manifest.yaml
requires_ffmpeg: true

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

This section confirms sensitive credential handling, including browser-based login flows and token write-back behavior. In a skill that launches subprocesses and fetches remote media URLs, any mishandling of credential files or auth flows can lead to token theft, unauthorized API use, or credential leakage into logs or unintended directories.

Content

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

md
- **能力与管道**:步骤级说明见 **§1**;`run_render` 职责与子进程见 **§5**(不在此重复链路)。
- **主凭据 / 路径 / primaryEnv**:见 **`manifest.yaml`**;路径与写回行为另见 **§3.2** 持久性表「凭据状态」及 **`CHANJING_OPENAPI_CREDENTIALS_DIR`**(兼容 **`CHANJING_CONFIG_DIR`**)。
- **敏感与合规**:勿回显完整密钥、**勿将 `credentials.json` 提交版本库**;权限建议 **`0700` / `0600`**(配置脚本尽量设置)。
- **信任与出站行为**:HTTPS、按返回 URL 拉取媒体、**`--output-dir`** 落盘等细节见 **§3.2**「典型副作用」与持久性表;须自行判断是否信任蝉镜主机与链接。
- **浏览器**:缺凭证时的 **`webbrowser.open` / `open_login_page.py`** 见 **§3.2** 同表。
- **Agent 策略**:**`manifest.yaml`** 中 **`agentPolicy`**(非 always、不改其它 skill)。

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

The documentation specifies a default credential location under the user home directory and states that app_id, secret_key, and refreshed access_token data are written there. This is dangerous because predictable plaintext secret locations are common exfiltration targets, and the same skill also writes other artifacts and invokes subordinate scripts, increasing the chance of unintended disclosure or cross-task access.

Content

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

md
| 类别 | 写入什么 | 典型位置 | 用户如何控制 |
|------|----------|----------|----------------|
| **凭据状态** | 经配置写入的 **`app_id` / `secret_key`**、刷新后的 **`access_token`、 `expire_in`** 等 | **`CHANJING_OPENAPI_CREDENTIALS_DIR/credentials.json`**(默认 **`~/.chanjing/credentials.json`**;兼容 **`CHANJING_CONFIG_DIR`**) | 设置推荐名或旧名;或迁移/删除该文件;**勿**将秘钥提交版本库。 |
| **一键成片工件** | **`final_one_click.mp4`**、**`workflow_result.json`**、**`work/`** 等 | 由 **`run_render.py --output-dir`** 指定(常见为某次任务下的 **`outputs/<任务名>/`**) | 选用明确的 **`--output-dir`**;任务结束后按需保留或删除该目录。 |
| **其它下载类脚本**(子 skill) | 合成结果等到本地 | 各 skill 的 **`download_result.py`** 等:默认多在当前工作目录下 **`outputs/<产品线>/`**,或 **`--output`** 绝对路径 | 在预期 cwd 下执行,或始终传 **`--output`**;详见对应 skill 的 **`SKILL.md`**。 |
| **临时/过程文件** | TTS 合并、切段、上传前缓存等 | 多在上述 **`output-dir` 下的 `work/`** 或脚本约定子目录 | 随输出目录一并管理。 |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
品线>/`**,或 **`--output`** 绝对路径 | 在预期 cwd 下执行,或始终传 **`--output`**;详见对应 skill 的 **`SKILL.md`**。 |

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 57)May include surrounding context.

yaml
credentials:
  model: credentials_json
  defaultPath: "~/.chanjing/credentials.json"
  directoryEnv: CHANJING_OPENAPI_CREDENTIALS_DIR
  fileName: credentials.json
  sensitiveFields:

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 59)May include surrounding context.

yaml
credentials:
  model: credentials_json
  defaultPath: "~/.chanjing/credentials.json"
  directoryEnv: CHANJING_OPENAPI_CREDENTIALS_DIR
  fileName: credentials.json
  sensitiveFields:

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 · tests/test_id_resolver.py (reported line 178)May include surrounding context.

python
credentials:
  model: credentials_json
  defaultPath: "~/.chanjing/credentials.json"
  directoryEnv: CHANJING_OPENAPI_CREDENTIALS_DIR
  fileName: credentials.json
  sensitiveFields:

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 · tests/test_run_render_stub.py (reported line 125)May include surrounding context.

python
credentials:
  model: credentials_json
  defaultPath: "~/.chanjing/credentials.json"
  directoryEnv: CHANJING_OPENAPI_CREDENTIALS_DIR
  fileName: credentials.json
  sensitiveFields:

Credential Access

High
Category
Privilege Escalation
Confidence
87% confidence
Finding

Persisting an access token on disk increases the window of exposure if the workspace, home directory, or credential store is read by other local processes, users, or compromised sibling skills. In this skill's context, the manifest also permits credential-file reads and writes, so long-lived cached tokens create a more attractive and reusable target than ephemeral in-memory credentials.

Content

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

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

clientPermissions:
  network:

Credential Access

High
Category
Privilege Escalation
Confidence
72% confidence
Finding

The client permissions explicitly allow reading the credentials.json file, which creates a direct path for the skill runtime or companion components to access high-value secrets. While reading credentials may be operationally necessary, this is still a real security risk because the same skill also has network capability and can invoke subprocesses, increasing the blast radius if any downstream code is compromised.

Content

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

yaml
- open-api.chanjing.cc
  filesystem:
    read:
      - "${CHANJING_OPENAPI_CREDENTIALS_DIR or CHANJING_CONFIG_DIR or ~/.chanjing}/credentials.json"
      - "${SKILLS_DIR or CHANJING_ONE_CLICK_VIDEO_SKILLS_ROOT or CHAN_SKILLS_DIR or repo_root}/skills/"
      - user_workflow_and_output_paths
    write:

Credential Access

High
Category
Privilege Escalation
Confidence
78% confidence
Finding

Allowing writes to the credentials.json file enables modification, replacement, or poisoning of stored credentials and tokens. In a skill that can call sibling skills and access the network, writable credential storage raises the risk of persistent compromise, token swapping, or malicious reconfiguration if any execution path is abused.

Content

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

yaml
- "${SKILLS_DIR or CHANJING_ONE_CLICK_VIDEO_SKILLS_ROOT or CHAN_SKILLS_DIR or repo_root}/skills/"
      - user_workflow_and_output_paths
    write:
      - "${CHANJING_OPENAPI_CREDENTIALS_DIR or CHANJING_CONFIG_DIR or ~/.chanjing}/credentials.json"
      - user_output_directory
  browser:
    mayOpenForAuth: true

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/run_render.py (reported line 195)May include surrounding context.

python
capture_output=True,
        text=True,
        timeout=timeout,
        env={**os.environ, **(env or {})},
    )
    if r.returncode != 0:
        msg = (r.stderr or r.stdout or "").strip() or f"exit {r.returncode}"

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file hard-codes an East Asian default for any recognizable person when the prompt is ambiguous, without requiring user consent or a narrowly scoped, documented regional mode. In a general-purpose video creation skill, this creates systematic demographic steering and biased outputs, which can misrepresent subjects, exclude other groups, and override user intent in subtle ways.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The historical-content logic defaults ambiguous non-contemporary narratives into a China/East Asia portrayal, including facial features, clothing, and civilizational markers, even when the user has not explicitly requested that framing. This can rewrite historical context, introduce cultural inaccuracies, and impose identity assumptions on generated media at scale.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

The fallback rule explicitly applies a China-context default whenever the script cannot uniquely determine ethnicity or civilization, which embeds locale bias directly into the generation pipeline. Because this skill auto-generates finished videos, the bias propagates into user-facing content automatically and can consistently skew outputs without visibility or consent.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · tests/test_id_resolver.py (reported line 70)May include surrounding context.

python
capture_output=True,
        text=True,
        timeout=timeout,
        env=os.environ.copy(),
    )
    if r.returncode != 0:
        raise RuntimeError(

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill documentation describes capabilities including environment-variable use, file reads/writes, outbound HTTPS, and subprocess execution, but it does not declare an explicit tool scope such as permissions or allowed-tools in the skill file. That creates a trust-boundary gap: an agent or reviewer cannot easily determine the minimum privileges required, increasing the risk of over-broad execution in a credentialed, networked workflow.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The natural-language instructions say '默认偏好年轻、有活力的形象' and direct the agent to prioritize youth-coded labels unless the user explicitly requests otherwise. This encodes a demographic preference as a default behavior rather than offering a neutral choice or asking the user, which is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

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

md
| **其它下载类脚本**(子 skill) | 合成结果等到本地 | 各 skill 的 **`download_result.py`** 等:默认多在当前工作目录下 **`outputs/<产品线>/`**,或 **`--output`** 绝对路径 | 在预期 cwd 下执行,或始终传 **`--output`**;详见对应 skill 的 **`SKILL.md`**。 |
| **临时/过程文件** | TTS 合并、切段、上传前缓存等 | 多在上述 **`output-dir` 下的 `work/`** 或脚本约定子目录 | 随输出目录一并管理。 |

**凭据文件**:路径与读写语义见上表 **凭据状态** 行;首次配置见 **`skills/chanjing-credentials-guard/SKILL.md`**。

---

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

L177 明确写着“不做:不产 plan/script/storyboard”,但 L151、L153 将 Plan → Script → Storyboard → Render 描述为该技能工作流的一部分,且 L229-L231 又把 video_plan、script_result、storyboard_result.scenes[] 列为输出 JSON 的组成部分。这里不是简单遗漏,而是文档对同一脚本/技能职责作出了相互冲突的表述,容易误导审计者和调用方对实际行为边界的判断。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The sample values and instructional text in this file are written in Chinese, including the topic, script, and field guidance, which implies a fixed language/locale for skill inputs. There is no accompanying note that the skill is China/Chinese-specific or that users may provide content in another language, so this can violate the language/locale choice policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This JSON file contains all user-facing content exclusively in Chinese, including the topic, script, subtitles, and voiceover text, with no indication that language selection is optional. Under the policy rule, forcing a specific language without user opt-in is a natural-language locale violation unless the constraint is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The natural-language comment says specific scene details must follow an upper-layer base ref_prompt in English, which imposes a language requirement. There is no nearby indication that users may choose another language or that the restriction is explicitly justified as a documented region- or model-specific constraint.

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/run_render.py (reported line 190)May include surrounding context.

python
def run_subprocess(
    argv: list[str], *, timeout: int = 900, env: Optional[dict] = None
) -> str:
    r = subprocess.run(
        argv,
        capture_output=True,
        text=True,

Static analysis

No suspicious patterns detected.