Back to skill

Security audit

Chanjing Content Creation Skill

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Chanjing media-creation skill, but it handles account secrets and media files with overly broad network and execution behavior that should be reviewed before installation.

Install only if you are comfortable giving this skill Chanjing account credentials and letting it upload/download media through Chanjing workflows. Avoid pasting SECRET_KEY values into chat, do not set CHANJING_API_BASE except to the official endpoint, review generated workflow inputs before rendering when costs matter, and rotate credentials if they were entered through chat or command-line arguments.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (5)

T01 · Skill Instruction Hijacking

Error
Location
orchestration/chanjing-one-click-video-creation/chanjing-one-click-video-creation-SKILL.md:14
Finding

Agent Instructions Override User Requirements and Force Unconfirmed Execution

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
common/base.py:69
Finding

Unvalidated API Base Can Receive Persistent Credentials and Access Tokens

Content
View full analysis
tuple[str | None, str | None]: body = request_json( "POST", f"{API_BASE}/open/v1/access_token", body={"app_id": app_id, "secret_key": secret_key}, ) ``` The manifest declares a narrower trust boundary: ```yaml permissions: network_mode: allowlist allowed_hosts: - open-api.chanjing.cc - www.chanjing.cc ``` ### Technical Analysis `CHANJING_API_BASE` is used without validating: - The URL scheme. - The normalized hostname. - The destination port. - Embedded URL credentials. - Compliance with the manifest allowlist. - Whether the destination is a public or private network address. The token-refresh request transmits both the persistent APP ID and secret key to this destination. Other clients transmit the resulting access token in an `access_token` header using the same uncontrolled base. Although an API-base override can be useful for testing, it must not be able to consume production credentials by default. The implementation contradicts the host allowlist declared in `manifest.yaml`. ### Attack Path 1. An attacker influences the process environment, wrapper script, CI configuration, or Agent execution environment. 2. The attacker sets `CHANJING_API_BASE` to an attacker-controlled URL, such as `https://attacker.example`. 3. The user ...[truncated 956 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
common/asset_download.py:25
Finding

Unrestricted Download URLs Enable SSRF and Resource Exhaustion

Content
View full analysis
Path: skill_root = Path(__file__).resolve().parents[1] default_dir = skill_root / "output" / outputs_subdir dest = output_path if output_path is not None else default_dir / infer_download_filename(url, default_basename) dest.parent.mkdir(parents=True, exist_ok=True) req = urllib.request.Request(url, headers={"User-Agent": user_agent}, method="GET") try: with urllib.request.urlopen(req, timeout=timeout) as resp, open(dest, "wb") as handle: handle.write(resp.read()) except Exception as exc: raise RuntimeError(f"download failed: {exc}") from exc if not dest.exists() or dest.stat().st_size == 0: raise RuntimeError("download failed: output file is empty") return dest ``` The renderer contains an equivalent unrestricted operation: ```python def download_url(url: str, dest: Path) -> 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()) ``` ### Technical Analysis The download functions accept arbitrary URLs without validating: - HTTPS usage. - Allowed hostnames. - Loopback, private, link-local, multicast, or reserved IP rang ...[truncated 1597 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
common/file_upload.py:74
Finding

Unvalidated Signed Upload URL Can Exfiltrate User-Selected Local Files

Content
View full analysis
tuple[bool, str | None]: put_req = urllib.request.Request( sign_url, data=content, headers={"Content-Type": mime_type}, method="PUT", ) try: with urllib.request.urlopen(put_req, timeout=120) as put_resp: if put_resp.status not in (200, 204): return False, f"upload returned status: {put_resp.status}" except Exception as exc: return False, f"upload failed: {exc}" return True, None ``` ```python def upload_local_file_via_chanjing( token: str, local_path: Path, service: str, *, poll_interval: float = 5.0, poll_timeout: float = 300.0, ready_statuses: set[Any], failed_statuses: set[Any] | None = None, pending_statuses: set[Any] | None = None, ) -> tuple[str | None, str | None]: if not local_path.is_file(): return None, f"file does not exist: {local_path}" payload, err = fetch_create_upload_url_payload(token, service, local_path.name) if err: return None, err sign_url = payload.get("sign_url") mime_type = payload.get("mime_type", "application/octet-stream") file_id = payload.get("file_id") if not sign_url or not file_id: return None, "response is missing sign_url or file_id" content = local_path.read_bytes() ok, put_err = put_file_to_sign_url(sign_url, content, mime_type) ``` ### Technical Analysis The destination for the local-file upload is taken from an API response and used without validating its scheme, hostname, port, resolved IP address, or redirect behavior. This is particularly dangerous in combination with the unvalidated `CHANJING_API_BASE`: a mal ...[truncated 1339 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
products/chanjing-credentials-guard/chanjing-credentials-guard-SKILL.md:55
Finding

Credential Setup Exposes Secrets Through Chat History and Process Arguments

Content
View full analysis
Remediation
View remediation
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
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (157)

Tainted flow: 'req' from os.environ.get (line 66, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The destination host for this authenticated request is derived from the CHANJING_API_BASE environment variable, so a modified runtime environment can redirect access_token-bearing requests to an attacker-controlled server. Because this module is a routing/upload helper for a skill that handles credentials and media uploads, SSRF-style redirection or credential exfiltration becomes materially more dangerous than a normal configurable endpoint.

Content

Scanner excerpt · common/file_upload.py (reported line 19)May include surrounding context.

python
"""GET file_detail;API 业务错误返回 (None, msg),网络异常向上抛出。"""
    url = f"{API_BASE}/open/v1/common/file_detail?id={urllib.parse.quote(file_id)}"
    req = urllib.request.Request(url, 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:
        return None, str(body.get("msg", "file_detail failed"))

Tainted flow: 'req' from os.environ.get (line 66, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

This request also uses API_BASE from the environment and sends the access token to whatever host that variable points to. An attacker who can influence environment variables or deployment config could cause the skill to request upload metadata from a malicious endpoint, exposing tokens and potentially returning attacker-controlled sign_url values for subsequent upload steps.

Content

Scanner excerpt · common/file_upload.py (reported line 67)May include surrounding context.

python
qs = urllib.parse.urlencode({"service": service, "name": name})
    url = f"{API_BASE}/open/v1/common/create_upload_url?{qs}"
    req = urllib.request.Request(url, 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:
        return None, str(body.get("msg", body))

Tainted flow: 'req' from os.environ.get (line 40, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The request URL is built from API_BASE, which is sourced from the CHANJING_API_BASE environment variable without validation or allowlisting. If an attacker can influence the runtime environment, they can redirect authenticated requests to an arbitrary host and capture the access_token header and request payloads, effectively turning this into SSRF plus credential exfiltration. In this skill context, the module is specifically a routing client for privileged Open API calls, so sending bearer-like tokens to an attacker-controlled endpoint is especially dangerous.

Content

Scanner excerpt · common/open_api_client.py (reported line 30)May include surrounding context.

python
url = f"{API_BASE}{path}{suffix}"
    req = urllib.request.Request(url, headers={"access_token": token}, method="GET")
    try:
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            body = json.loads(resp.read().decode("utf-8"))
    except Exception as exc:
        raise SkillHTTPError(str(exc)) from exc

Tainted flow: 'req' from os.environ.get (line 40, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The POST path has the same issue as the GET path: API_BASE comes from an environment variable and is concatenated directly into the destination URL before transmitting the access_token header. A compromised environment or launch configuration could silently reroute authenticated POST requests, exposing tokens and request bodies to an attacker-controlled server. Because this skill manages content-creation operations and credentials, this creates a meaningful exfiltration risk rather than a harmless configurability issue.

Content

Scanner excerpt · common/open_api_client.py (reported line 47)May include surrounding context.

python
method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            body = json.loads(resp.read().decode("utf-8"))
    except Exception as exc:
        raise SkillHTTPError(str(exc)) from exc

Tainted flow: 'req' from os.environ.get (line 301, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

The request target is derived from CHANJING_API_BASE and the code sends the access token in an HTTP header to that endpoint. If an attacker can control the environment or execution context, they can redirect requests to an attacker-controlled host and exfiltrate the bearer token and task metadata.

Content

Scanner excerpt · orchestration/chanjing-one-click-video-creation/scripts/run_render.py (reported line 274)May include surrounding context.

python
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"))

Tainted flow: 'req' from os.environ.get (line 301, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
92% confidence
Finding

The downloader fetches arbitrary URLs returned by upstream services or embedded in workflow data and writes the response directly to local files with no host restrictions or content validation. This creates an SSRF-style primitive and can be abused to make the agent access internal services or download malicious/unexpected content into the workspace.

Content

Scanner excerpt · orchestration/chanjing-one-click-video-creation/scripts/run_render.py (reported line 302)May include surrounding context.

python
def download_url(url: str, dest: Path) -> 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())

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| 顶层入口 | `SKILL.md` | 路由、消歧、契约摘要 |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
完整契约见 [`references/top-level-runtime-contract.md`](references/top-level-runtime-contract.md)。

Credential Access

High
Category
Privilege Escalation
Confidence
92% confidence
Finding

The manifest explicitly permits writing to ${SKILL_DIR}/.env, which is a credential-bearing file location. Even though credentials are declared as environment-based and persistAccessTokenOnDisk is false, allowing writes to a .env file creates a path for accidental secret persistence, overwriting trusted configuration, or planting attacker-controlled values that later influence authentication or API routing.

Content

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

yaml
- "${SKILL_DIR}/"
      - user_workflow_and_output_paths
    write:
      - "${SKILL_DIR}/.env"
      - user_output_directory
  browser:
    mayOpenForAuth: true

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
84% confidence
Finding

Passing the entire parent environment into every subprocess can leak secrets to child programs that do not need them, including ffmpeg/ffprobe and sibling scripts. In this skill context, the pipeline handles credentials and networked tools, so broad environment inheritance increases the blast radius if a child tool is compromised, verbose, or influenced by hostile inputs.

Content

Scanner excerpt · orchestration/chanjing-one-click-video-creation/scripts/run_render.py (reported line 235)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 template hard-codes a default China/Chinese-civilization setting and explicitly requires East Asian faces in inferred Chinese contexts unless the user specifies otherwise. In a generative media skill, this is a policy-level bias and unsafe demographic steering issue: it can override user intent, force ethnicity assignment for ambiguous subjects, and systematically produce exclusionary or culturally distorted outputs.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

This section mandates an ethnicity default and explicit ethnicity wording without user opt-in, which is a stronger form of sensitive-trait steering than ordinary style guidance. Because the file is a reusable orchestration template, the behavior can systematically affect many generated videos, causing repeated biased outputs, unfair representation, and compliance issues around handling protected characteristics.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
91% confidence
Finding

The document defaults historical depictions to a Chinese civilizational context and forbids alternative imagery absent contrary evidence, which steers cultural and ethnic representation in a prescriptive way. In a prompt-generation pipeline, this can overwrite ambiguous or multicultural narratives, produce historically inaccurate outputs, and systematically privilege one cultural default without user authorization.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

This rule applies a default China-context and East Asian appearance whenever the script does not uniquely determine identity or civilization, embedding protected-attribute and geopolitical assumptions into the generation process. Since this is part of orchestration logic, it can silently bias many outputs and make the skill less trustworthy for general-purpose content creation.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
89% confidence
Finding

Passing os.environ.copy() into a spawned subprocess forwards all ambient secrets and tokens to child scripts, even though the test appears to need only specific Chanjing credentials. If any called script logs, leaks, or mishandles its environment, unrelated secrets from the parent process could be exposed unnecessarily.

Content

Scanner excerpt · orchestration/chanjing-one-click-video-creation/tests/test_id_resolver.py (reported line 71)May include surrounding context.

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

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The documentation explicitly directs the skill to read app_id and secret_key from .env, which is direct credential access at the product-skill layer. In an agentic environment, this is high risk because prompt-driven execution paths may cause unnecessary secret exposure, reuse, or leakage through logs, subprocesses, or downstream tooling.

Content

Scanner excerpt · products/chanjing-avatar/chanjing-avatar-SKILL.md (reported line 93)May include surrounding context.

json
{
  "app_id": "<从 .env 的 CHANJING_APP_ID 读取>",
  "secret_key": "<从 .env 的 CHANJING_SECRET_KEY 读取>"
}

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The secret_key field is specifically called out as being sourced from .env, which exposes a long-lived secret to a lower-trust execution layer. Because this skill orchestrates API calls and scripts, the presence of raw secret-handling instructions increases the chance of accidental disclosure or misuse beyond the centralized router’s intended control.

Content

Scanner excerpt · products/chanjing-avatar/chanjing-avatar-SKILL.md (reported line 94)May include surrounding context.

json
{
  "app_id": "<从 .env 的 CHANJING_APP_ID 读取>",
  "secret_key": "<从 .env 的 CHANJING_SECRET_KEY 读取>"
}

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · products/chanjing-credentials-guard/chanjing-credentials-guard-SKILL.md (reported line 83)May include surrounding context.

md
### Step 2: Branch on result

- **If already configured**: Ask the user—**“You already have Chanjing APP_ID/SECRET_KEY configured. Do you want to re-apply and overwrite the current config?”**
  - If the user confirms re-apply, run the “Guide steps” below.
  - If the user says no, stop; do not open the login page or show config commands.

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 · products/chanjing-credentials-guard/reference.md (reported line 5)May include surrounding context.

md
## API (chanjing-openapi.yaml)

### Get Access Token

| Item | Value |
|------|--------|

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 · products/chanjing-tts-voice-clone/chanjing-tts-voice-clone-SKILL.md (reported line 57)May include surrounding context.

md
## API (chanjing-openapi.yaml)

### Get Access Token

| Item | Value |
|------|--------|

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · common/base.py (reported line 134)May include surrounding context.

python
| Variable | Description | Default |
|----------|-------------|---------|
| CHANJING_ENV_FILE | Credentials file path | skills/chanjing-content-creation-skill/.env |
| CHANJING_API_BASE | API base URL | https://open-api.chanjing.cc |

## Login and obtaining keys

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · orchestration/chanjing-one-click-video-creation/manifest.yaml (reported line 69)May include surrounding context.

yaml
| Variable | Description | Default |
|----------|-------------|---------|
| CHANJING_ENV_FILE | Credentials file path | skills/chanjing-content-creation-skill/.env |
| CHANJING_API_BASE | API base URL | https://open-api.chanjing.cc |

## Login and obtaining keys

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · orchestration/chanjing-one-click-video-creation/manifest.yaml (reported line 72)May include surrounding context.

yaml
| Variable | Description | Default |
|----------|-------------|---------|
| CHANJING_ENV_FILE | Credentials file path | skills/chanjing-content-creation-skill/.env |
| CHANJING_API_BASE | API base URL | https://open-api.chanjing.cc |

## Login and obtaining keys

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · products/chanjing-credentials-guard/reference.md (reported line 54)May include surrounding context.

md
| Variable | Description | Default |
|----------|-------------|---------|
| CHANJING_ENV_FILE | Credentials file path | skills/chanjing-content-creation-skill/.env |
| CHANJING_API_BASE | API base URL | https://open-api.chanjing.cc |

## Login and obtaining keys

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · products/chanjing-tts-voice-clone/chanjing-tts-voice-clone-SKILL.md (reported line 70)May include surrounding context.

md
| Variable | Description | Default |
|----------|-------------|---------|
| CHANJING_ENV_FILE | Credentials file path | skills/chanjing-content-creation-skill/.env |
| CHANJING_API_BASE | API base URL | https://open-api.chanjing.cc |

## Login and obtaining keys