Back to skill

Security audit

Chanjing Credentials Guard

Security checks for vulnerabilities and agentic risk

Overview

This skill appears intended to manage Chanjing credentials, but its handling of secrets has enough avoidable exposure risk that users should review it carefully before installing.

Install only if you trust this publisher and are comfortable with Chanjing AK/SK and tokens being stored locally. Before use, avoid setting CHANJING_OPENAPI_BASE_URL or CHANJING_API_BASE unless you fully trust the endpoint, avoid putting real secret keys in shell history or CI logs, and treat any printed access token as sensitive credential material.

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/chanjing_get_token.py:22
Finding

Environment-Controlled API Base URL Can Exfiltrate Chanjing Credentials

Content
View full analysis

Vulnerability Details

File Location: scripts/chanjing_get_token.py, lines 22–34, 67–76, and 110–111
Vulnerability Type: Unvalidated credential transmission endpoint
Risk Level: High

Vulnerable Code

python
def openapi_base_url() -> str:
    return (
        os.environ.get("CHANJING_OPENAPI_BASE_URL")
        or os.environ.get("CHANJING_API_BASE")
        or _DEFAULT_OPENAPI_BASE
    ).rstrip("/")


CONFIG_DIR = credentials_config_dir()
CONFIG_FILE = CONFIG_DIR / "credentials.json"
API_URL = openapi_base_url() + "/open/v1/access_token"
python
def fetch_token(app_id, secret_key):
    req = urllib.request.Request(
        API_URL,
        data=json.dumps({"app_id": app_id, "secret_key": secret_key}).encode("utf-8"),
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    with urllib.request.urlopen(req, timeout=30) as resp:
        body = json.loads(resp.read().decode("utf-8"))
    return body
python
try:
    resp = fetch_token(app_id, secret_key)
except Exception as e:
    print(f"请求 Token 失败: {e}", file=sys.stderr)
    sys.exit(1)

Technical Analysis

The token client reads CHANJING_OPENAPI_BASE_URL or the legacy CHANJING_API_BASE directly from the process environment and uses the resulting value as the destination for a request containing both app_id and secret_key.

The implementation does not validate:

  • That the URL uses HTTPS.
  • That the destination hostname is open-api.chanjing.cc.
  • That the port is expected.
  • That the URL does not contain embedded user information.
  • That redirects remain on the approved host.

Although manifest.yaml documents a network allowlist, the Python code does not enforce that allowlist itself. Security therefore depends on the runtime sandbox applying the manifest correctly. In an execution environment that does not enforce it, or where network policy ...[truncated 1508 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove production endpoint overrides unless custom deployments are an explicit requirement.
  2. Parse the URL with urllib.parse.urlsplit and require:
    • Scheme exactly equal to https.
    • Hostname exactly equal to open-api.chanjing.cc, or a narrowly defined trusted-host allowlist.
    • No embedded username or password.
    • Only an approved port, normally 443.
  3. Reject malformed URLs and values containing unexpected path, query, or fragment components.
  4. Disable redirects for the credential request or validate every redirect destination against the same HTTPS hostname allowlist.
  5. Treat manifest-level network restrictions as defense in depth rather than the only enforcement mechanism.
  6. If custom endpoints must remain supported, require explicit user approval and clearly warn that AK/SK will be transmitted to the configured host.
  7. Add automated tests proving that HTTP URLs, unapproved hosts, unusual ports, and cross-host redirects are rejected.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/chanjing_config.py:115
Finding

Secret Key Is Accepted Through Exposed Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/chanjing_config.py, lines 115–117 and 124–125; documented in SKILL.md, lines 89–94, 124–127, and 190–192
Vulnerability Type: Sensitive information exposure through process arguments and shell history
Risk Level: Medium

Vulnerable Code

python
parser.add_argument("--ak", help="Access Key (app_id)")
parser.add_argument("--sk", help="Secret Key (secret_key)")
parser.add_argument("--status", "-s", action="store_true", help="查看配置状态")
python
if args.ak and args.sk:
    set_credentials(args.ak, args.sk)
    return

The documented workflow explicitly instructs users to invoke the script with the secret as a command-line argument:

bash
python scripts/chanjing_config.py --ak <your_app_id> --sk <your_secret_key>
python skills/chanjing-credentials-guard/scripts/chanjing_config.py --ak <your_app_id> --sk <your_secret_key>

Technical Analysis

Command-line arguments are not an appropriate default transport for long-lived secrets. Depending on the platform and execution environment, argument values may be exposed through:

  • Shell history files.
  • Process inspection interfaces and process-monitoring tools.
  • Terminal session recording.
  • CI/CD command logs.
  • Agent or orchestration telemetry.
  • Audit and endpoint-monitoring products.
  • Wrapper scripts that log complete commands.

The Skill correctly tells users not to paste credentials into chat, but the recommended replacement still creates several local disclosure channels. Applying restrictive permissions to credentials.json does not protect the secret before it reaches that file.

Attack Path

  1. The victim follows the documented command and supplies the real Secret Key using --sk.
  2. The shell stores the complete command in its history, or a process-monitoring or automation system captures the argument list.
  3. Another local user, administrator, compromi ...[truncated 763 chars]
Remediation
View remediation

Remediation Suggestions

  1. Make interactive protected input the default:
    python
    from getpass import getpass
    secret_key = getpass("Secret Key: ")
    
  2. Accept the App ID interactively or through a non-secret option, while reading the Secret Key from getpass, protected stdin, or an operating-system credential store.
  3. Remove --sk from the primary documented workflow.
  4. If backward compatibility requires retaining --sk, mark it as unsafe, issue a warning, and recommend immediate shell-history cleanup and key rotation after accidental exposure.
  5. Support secure automation through a file descriptor or protected input file with strict ownership and mode checks rather than a command-line value.
  6. Ensure error messages, debug logs, and exception handlers never reproduce the supplied secret.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/chanjing_get_token.py:101
Finding

Bearer Access Token Is Printed Directly to Standard Output

Content
View full analysis

Vulnerability Details

File Location: scripts/chanjing_get_token.py, lines 101–103 and 128–130; behavior documented in SKILL.md, lines 167–168
Vulnerability Type: Sensitive information exposure through standard output
Risk Level: Medium

Vulnerable Code

python
if token and expire_in > now + BUFFER_SECONDS:
    print(token)
    return 0
python
data["access_token"] = new_token
data["expire_in"] = new_expire
write_config(data)
print(new_token)
return 0

Technical Analysis

The script emits the complete bearer access token to standard output whenever it returns a cached token or successfully obtains a new one. Standard output is frequently captured by:

  • AI-agent and Skill execution frameworks.
  • CI/CD systems.
  • Terminal recorders.
  • Shell command substitution and wrapper scripts.
  • Centralized logging and observability platforms.
  • Support diagnostics and execution transcripts.

A bearer token generally grants access based on possession alone. Printing it by default expands its exposure from the protected credential file to every system that records command output. This undermines the otherwise restrictive 0600 file permission used for persisted credentials.

Attack Path

  1. The victim or an automated agent runs scripts/chanjing_get_token.py.
  2. The script prints the valid access token to stdout.
  3. The execution framework, terminal recorder, CI service, or logging wrapper stores the output.
  4. An unauthorized user gains read access to the captured output.
  5. The attacker extracts and reuses the bearer token before it expires.

Impact Assessment

The attacker can perform Chanjing API operations authorized by the token until it expires or is revoked. The exact scope is limited to the permissions represented by that token.

This does not directly disclose the underlying Secret Key, but it enables temporary account or API impersonation. Exposure ...[truncated 118 chars]

Remediation
View remediation

Remediation Suggestions

  1. Do not print the token by default. Return only a success or status message.
  2. Keep the token in the protected credential file or an operating-system credential store and let authorized clients read it through a controlled interface.
  3. If machine-readable token output is essential, require an explicit option such as --print-token and display a clear warning that output must not be logged.
  4. Prefer passing tokens to child processes through a protected pipe or inherited file descriptor rather than terminal-visible stdout.
  5. Configure Skill runners and CI systems to redact token-shaped output as defense in depth.
  6. Document token revocation and rotation procedures for users who accidentally expose command output.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill claims to operate via local commands only, yet it instructs opening a remote login page and interacting with a remote service. That creates a trust-boundary expansion not captured by the description, increasing the chance that users trigger external actions and credential workflows they did not expect from a supposedly local-only helper.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill claims to operate via local commands only, yet it instructs opening a remote login page and interacting with a remote service. That creates a trust-boundary expansion not captured by the description, increasing the chance that users trigger external actions and credential workflows they did not expect from a supposedly local-only helper.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The skill is explicitly designed to access and persist credentials, including long-lived AK/SK and a usable access token on disk. Storing and handling active credentials is inherently sensitive, and if the file permissions, path controls, or output handling are weak, an attacker or adjacent process could obtain credentials and impersonate the user against the Chanjing API.

Content

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

md
description: >-
  Guide users to configure local Chanjing credentials safely via local
  commands only, and validate local token status when needed.
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
96% confidence
Finding

The documentation specifies a plaintext-style credentials file containing app_id, secret_key, and access_token in a predictable path under the user's home directory, overridable by environment variables. Predictable credential storage combined with token persistence increases theft risk from local malware, misconfigured permissions, backups, logs, or malicious path redirection via environment overrides.

Content

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

AK/SK and Token are read from the same config file. Path and format follow the script scripts/chanjing_config.py in this skill.

  • Path: ~/.chanjing/credentials.json(目录由 CHANJING_OPENAPI_CREDENTIALS_DIR 覆盖,兼容 CHANJING_CONFIG_DIR)
  • Format:
json
{

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

The skill instructs reading the credential file to determine whether AK/SK are configured, reinforcing routine access to highly sensitive local secrets. In context, the skill is a credential-management helper, so some secret access is expected, but the danger is increased because related workflow steps also fetch, persist, and expose tokens, broadening the blast radius of any misuse or compromise.

Content

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

md
### Step 1: Check if already configured

Check if local AK/SK already exists (read `~/.chanjing/credentials.json` for non-empty `app_id` and `secret_key`, or run `python skills/chanjing-credentials-guard/scripts/chanjing_config.py --status`).

### Step 2: Branch on result

Credential Access

High
Category
Privilege Escalation
Confidence
88% confidence
Finding

The manifest explicitly enables persistAccessTokenOnDisk: true, meaning access tokens are stored locally in credentials.json. Persisting bearer tokens on disk increases the chance of token theft through local compromise, accidental backup/sync, or overly broad filesystem permissions, especially because the same manifest also grants read/write access to the credentials location.

Content

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

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

clientPermissions:
  network:

Credential Access

High
Category
Privilege Escalation
Confidence
80% confidence
Finding

The manifest grants write access not only to credentials.json but to the entire credentials directory. Directory-level write permission creates unnecessary opportunity to alter, replace, or add files in the credential store, which can facilitate credential tampering, persistence, or abuse if the skill implementation is compromised or behaves unexpectedly.

Content

Scanner excerpt · manifest.yaml (reported line 78)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"
      - "${CHANJING_OPENAPI_CREDENTIALS_DIR or CHANJING_CONFIG_DIR or ~/.chanjing}/"
  browser:
    mayOpenForAuth: true

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 · 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
87% confidence
Finding

This line discloses the exact default credential file location and confirms that AK/SK are read from it, which materially lowers the effort for credential discovery by malware, a local attacker, or unsafe automation. In a credential-management skill this context makes the reference relevant, but still dangerous because it centralizes secret location details without paired safeguards.

Content

Scanner excerpt · reference.md (reported line 42)May include surrounding context.

AK/SK are read from a config file. Path and format follow scripts/chanjing_config.py (see CONFIG_DIR, CONFIG_FILE, and read_config() in that script).

File path: ~/.chanjing/credentials.json (default; override with env CHANJING_CONFIG_DIR)

json
{

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

yaml
#!/usr/bin/env python3
"""
获取有效的 access_token。
AK/SK 从与 chanjing_config.py 相同的配置文件中读取(CONFIG_DIR/credentials.json,见 chanjing_config.py)。
若无 AK/SK 则输出引导信息并退出;若 Token 过期则自动申请并保存。
用法: python chanjing_get_token.py
输出: 成功时打印 access_token 到 stdout;失败时打印错误到 stderr 并 exit 1

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

yaml
#!/usr/bin/env python3
"""
获取有效的 access_token。
AK/SK 从与 chanjing_config.py 相同的配置文件中读取(CONFIG_DIR/credentials.json,见 chanjing_config.py)。
若无 AK/SK 则输出引导信息并退出;若 Token 过期则自动申请并保存。
用法: python chanjing_get_token.py
输出: 成功时打印 access_token 到 stdout;失败时打印错误到 stderr 并 exit 1

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
#!/usr/bin/env python3
"""
获取有效的 access_token。
AK/SK 从与 chanjing_config.py 相同的配置文件中读取(CONFIG_DIR/credentials.json,见 chanjing_config.py)。
若无 AK/SK 则输出引导信息并退出;若 Token 过期则自动申请并保存。
用法: python chanjing_get_token.py
输出: 成功时打印 access_token 到 stdout;失败时打印错误到 stderr 并 exit 1

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

yaml
#!/usr/bin/env python3
"""
获取有效的 access_token。
AK/SK 从与 chanjing_config.py 相同的配置文件中读取(CONFIG_DIR/credentials.json,见 chanjing_config.py)。
若无 AK/SK 则输出引导信息并退出;若 Token 过期则自动申请并保存。
用法: python chanjing_get_token.py
输出: 成功时打印 access_token 到 stdout;失败时打印错误到 stderr 并 exit 1

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

python
#!/usr/bin/env python3
"""
获取有效的 access_token。
AK/SK 从与 chanjing_config.py 相同的配置文件中读取(CONFIG_DIR/credentials.json,见 chanjing_config.py)。
若无 AK/SK 则输出引导信息并退出;若 Token 过期则自动申请并保存。
用法: python chanjing_get_token.py
输出: 成功时打印 access_token 到 stdout;失败时打印错误到 stderr 并 exit 1

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

python
#!/usr/bin/env python3
"""
获取有效的 access_token。
AK/SK 从与 chanjing_config.py 相同的配置文件中读取(CONFIG_DIR/credentials.json,见 chanjing_config.py)。
若无 AK/SK 则输出引导信息并退出;若 Token 过期则自动申请并保存。
用法: python chanjing_get_token.py
输出: 成功时打印 access_token 到 stdout;失败时打印错误到 stderr 并 exit 1

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

python
#!/usr/bin/env python3
"""
获取有效的 access_token。
AK/SK 从与 chanjing_config.py 相同的配置文件中读取(CONFIG_DIR/credentials.json,见 chanjing_config.py)。
若无 AK/SK 则输出引导信息并退出;若 Token 过期则自动申请并保存。
用法: python chanjing_get_token.py
输出: 成功时打印 access_token 到 stdout;失败时打印错误到 stderr 并 exit 1

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

python
#!/usr/bin/env python3
"""
获取有效的 access_token。
AK/SK 从与 chanjing_config.py 相同的配置文件中读取(CONFIG_DIR/credentials.json,见 chanjing_config.py)。
若无 AK/SK 则输出引导信息并退出;若 Token 过期则自动申请并保存。
用法: python chanjing_get_token.py
输出: 成功时打印 access_token 到 stdout;失败时打印错误到 stderr 并 exit 1

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script performs outbound network access to request a fresh access token from a remote API, even though the skill metadata says credential handling should occur via local commands only. This mismatch matters because users and higher-level tooling may trust the skill to stay local, while it actually transmits stored credentials off-host and changes local state by refreshing and persisting tokens.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill documents capabilities that include environment access, file read/write, shell execution, and outbound network activity, but it does not declare an explicit tool scope such as permissions or allowed-tools. That weakens containment and reviewability because consumers cannot easily tell what actions the skill may invoke, especially around credential files and token retrieval.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file mixes English and Chinese, but key instructional content begins with Chinese-only sections such as '功能说明' and operational guidance in Chinese. Under the policy, forcing a specific language without user opt-in can be a natural-language policy violation unless the locale constraint is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
2. **Require local setup command** after the user obtains keys:
   - Show command only; user runs it locally in terminal.
3. **Do not request secrets in chat**:
   - Never ask user to paste AK/SK in conversation.
   - Never echo or store AK/SK in chat summaries.
4. **After setting**:
   - Ask user to run status check and then proceed to target action.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

python skills/chanjing-credentials-guard/scripts/chanjing_config.py --ak <your_app_id> --sk <your_secret_key>

text
4. **Secret handling rule**:
- Do not ask user to paste AK/SK in chat.
- If user shares secret in chat anyway, remind them to rotate keys and continue with local-command-only flow.
5. **After setting**:
- Run status check:

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
- This skill only handles **local credential guidance**.
- It does not require install hooks or elevated/system-wide privileges.
- It should not automatically execute unrelated skills.
- It should not accept AK/SK via chat content.

## Shell Config

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The document instructs users to store long-lived AK/SK secrets and optional access tokens in a local JSON file but does not warn that this is plaintext credential storage or recommend file permission hardening. This increases the chance that secrets are exposed through local compromise, backups, shared home directories, or accidental disclosure, especially because the exact path and schema are documented.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module documentation describes behavior in a way that understates what the script really does: it not only retrieves a token but automatically requests a new one from a remote service and saves it locally. Security-relevant documentation mismatches are dangerous because reviewers, users, and automated policy systems may approve or invoke the script under false assumptions about data flow and side effects.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.