Back to skill

Security audit

Zyt TTS

Security checks for vulnerabilities and agentic risk

Overview

This Chanjing TTS skill is purpose-aligned and discloses its credential use, but users should treat its local credentials file as sensitive.

Install only if you intend to use Chanjing TTS and are comfortable storing app_id, secret_key, and cached access_token in a local JSON file. Keep ~/.chanjing or CHANJING_CONFIG_DIR private, avoid shared directories, and remember the credentials are sent to Chanjing's API to obtain tokens. Some scripts named in the documentation were not present in the reviewed artifact, so functionality may be incomplete.

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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/_auth.py:47
Finding

Credential File Permissions Are Applied Non-Atomically and Permission Failures Are Suppressed

Content
View full analysis

Vulnerability Details

File Location: scripts/_auth.py:47-59
Vulnerability Type: Insecure credential storage
Risk Level: Medium

python
def write_config(data):
    CONFIG_DIR.mkdir(parents=True, exist_ok=True)
    try:
        os.chmod(CONFIG_DIR, 0o700)
    except Exception:
        pass
    with open(CONFIG_FILE, "w", encoding="utf-8") as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    try:
        os.chmod(CONFIG_FILE, 0o600)
    except Exception:
        pass

Technical Analysis

The configuration file contains app_id, secret_key, and a cached access_token. It is created using the process's default file-creation permissions and restricted to mode 0600 only after its contents have been written. This creates a non-atomic protection sequence in which the file's initial permissions depend on the active umask.

The parent directory is similarly hardened after creation rather than created with a guaranteed restrictive mode. If the configured directory already exists, is shared, resides on a filesystem with unsuitable permission semantics, or a permission change fails, sensitive data may be exposed.

Both chmod operations suppress every exception, so execution continues even when credential protection cannot be established. The implementation also does not verify the file's resulting owner, type, or permissions.

Attack Path

  1. A victim runs the Skill with a permissive umask or sets CHANJING_CONFIG_DIR to an existing shared or insufficiently protected directory.
  2. write_config() opens and writes credentials.json using process-default creation permissions.
  3. The subsequent chmod() fails, is ineffective on the selected filesystem, or cannot correct exposure that occurred during creation.
  4. The exception is silently ignored, and the program continues as if credential storage were secure.
  5. Another local user or process with directory access reads credentials.json.
  6. The exposed secret_key or c ...[truncated 704 chars]
Remediation
View remediation

Remediation Suggestions

  • Create the configuration directory with mode 0700 from the outset and verify its ownership and final permissions.
  • Write credentials to a securely created temporary file using exclusive creation and mode 0600, then atomically replace the destination with os.replace().
  • Flush and synchronize the temporary file before replacement where durability is required.
  • Reject symlinks and non-regular destination files where platform APIs permit.
  • Do not suppress permission errors. Fail closed with a clear error if secure storage cannot be established.
  • Verify the final file owner and permissions after writing.
  • Consider separating the long-lived secret key and cached access token from non-sensitive configuration and using an operating-system credential store where available.

A hardened implementation should ensure that sensitive content is never present in a file with process-default or unverified permissions, even temporarily.

Vulnerability Patterns
  • 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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (18)

Credential Access

High
Category
Privilege Escalation
Confidence
84% confidence
Finding

The skill description explicitly states it reads app_id and secret_key from a local credentials file and uses them to mint access tokens. Accessing local secrets is sensitive behavior and, without narrow scoping and strong handling guarantees, can enable unintended disclosure or misuse of API credentials.

Content

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

md
---
name: zyt-tts-test
description: Use Chanjing TTS API to convert text to speech by listing voices, creating synthesis tasks, and polling task status. This skill reads app_id and secret_key from ~/.chanjing/credentials.json or $CHANJING_CONFIG_DIR/credentials.json, refreshes access_token for API calls, and returns login guidance when credentials are missing or invalid.
metadata:
  openclaw:
    requires:

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

This section instructs the skill to read credentials from ~/.chanjing/credentials.json or an environment-controlled directory. Reading authentication material from disk is a real sensitive capability, and the env-controlled alternate path broadens the trust boundary because a manipulated environment can redirect the skill to attacker-chosen files.

Content

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

md
This skill reads credentials from:

- `~/.chanjing/credentials.json`
- or `$CHANJING_CONFIG_DIR/credentials.json`

The credentials file should contain:

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The continued credential-loading guidance reinforces that the skill consumes local secret material from configurable paths. In an agent setting, any workflow that normalizes reading local credentials without strict controls raises the risk of secret harvesting or accidental disclosure through logs, errors, or downstream tool use.

Content

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

md
This skill reads credentials from:

- `~/.chanjing/credentials.json`
- or `$CHANJING_CONFIG_DIR/credentials.json`

The credentials file should contain:

Credential Access

High
Category
Privilege Escalation
Confidence
82% confidence
Finding

This section describes obtaining an access token using locally stored app_id and secret_key, which is legitimate for API auth but still a sensitive flow. The danger is not the token exchange itself; it is that the skill operationalizes local secret use and network authentication without describing safeguards for token storage, output redaction, or least privilege.

Content

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

md
## API Notes

### Access Token

Read `app_id` and `secret_key` from the local credentials file. If there is no valid token, request one from:

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 · SKILL.md (reported line 242)May include surrounding context.

md
| Code | Description |
|---|---|
| `0` | success |
| `10400` | access token verification failed |
| `40000` | parameter error |
| `50000` | system internal error |
| `51000` | system internal error |

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 · SKILL.md (reported line 307)May include surrounding context.

md
| Code | Description |
|---|---|
| `0` | success |
| `10400` | access token verification failed |
| `40000` | parameter error |
| `50000` | system internal error |
| `51000` | system internal error |

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 · SKILL.md (reported line 387)May include surrounding context.

md
| Code | Description |
|---|---|
| `0` | success |
| `10400` | access token verification failed |
| `40000` | parameter error |
| `50000` | system internal error |
| `51000` | system internal error |

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

python
# 鉴权:从 CONFIG_DIR/credentials.json 读取 AK/SK
# 实现:AK/SK 校验、Token 校验与刷新;默认不自动打开浏览器,仅返回登录引导信息
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 10)May include surrounding context.

python
# 鉴权:从 CONFIG_DIR/credentials.json 读取 AK/SK
# 实现:AK/SK 校验、Token 校验与刷新;默认不自动打开浏览器,仅返回登录引导信息
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 17)May include surrounding context.

python
# 鉴权:从 CONFIG_DIR/credentials.json 读取 AK/SK
# 实现:AK/SK 校验、Token 校验与刷新;默认不自动打开浏览器,仅返回登录引导信息
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 26)May include surrounding context.

python
# 鉴权:从 CONFIG_DIR/credentials.json 读取 AK/SK
# 实现:AK/SK 校验、Token 校验与刷新;默认不自动打开浏览器,仅返回登录引导信息
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 27)May include surrounding context.

python
# 鉴权:从 CONFIG_DIR/credentials.json 读取 AK/SK
# 实现:AK/SK 校验、Token 校验与刷新;默认不自动打开浏览器,仅返回登录引导信息
import json
import os

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill documents capabilities to read environment variables and local files, write configuration files, invoke shell scripts, and make network requests, but it does not declare any explicit tool scope or permission boundaries. That creates an over-privileged execution model where an agent may use more powerful primitives than the user expects, increasing the chance of credential exposure or unintended local side effects.

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

md
- generate Chinese or English speech from text
- list available voices and choose a suitable one
- adjust speech speed
- create a TTS task and poll until completion
- return the remote audio URL and subtitle timestamps from the API result

## How to Use This Skill

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code writes sensitive credentials and access tokens to a local file and later reuses them, but the only nearby comments are implementation notes rather than user-facing warnings. Under SQP-2 for code files, access to credentials and file writes should have some visible disclosure such as a prompt, log, or explicit warning in documentation.

Content

No source excerpt is available for this finding.

Tainted flow: 'CONFIG_FILE' from os.environ.get (line 10, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

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

python
os.chmod(CONFIG_DIR, 0o700)
    except Exception:
        pass
    with open(CONFIG_FILE, "w", encoding="utf-8") as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    try:
        os.chmod(CONFIG_FILE, 0o600)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The function sends app_id and secret_key to a remote API endpoint to obtain an access token, but there is no confirmation prompt, print/log statement, or docstring warning users that local credentials will be transmitted over the network. This is a safety-relevant network operation involving sensitive data and falls within SQP-2.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The file's human-facing strings and comments are written exclusively in Chinese, including error messages returned to users, with no mechanism offering a language choice. This can violate the language/locale policy criterion when a skill forces a specific language without user opt-in.

Content

No source excerpt is available for this finding.