Back to skill

Security audit

Cn Api Router

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent model-configuration purpose, but its documented workflow exposes real API keys in command arguments, visible input, and printed output.

Review this skill before installing if you plan to use real provider keys. Avoid passing keys via --api-key, assume generated output and agent transcripts may contain the secret, and rotate any key that was pasted into this workflow or captured in logs.

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/setup_model.py:163
Finding
Plaintext API Key Exposure Through Command-Line Arguments, Visible Input, and Program Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup_model.py:163-175, 215-231`; `SKILL.md:33-38, 107-113` **Vulnerability Type**: Plaintext credential exposure **Risk Level**: Medium ### Vulnerable Code The interactive workflow reads the API key with ordinary visible terminal input and subsequently prints it as part of the generated JSON: ```python api_key = input("Enter API key: ").strip() if not api_key: print("❌ API key is required") return patch = generate_patch(provider_id, api_key) if patch: print("\n" + "=" * 60) print("📝 OpenClaw config.patch JSON:") print("=" * 60) print(json.dumps(patch, indent=2, ensure_ascii=False)) ``` The direct workflow obtains the key from a command-line argument and also prints the resulting configuration containing the plaintext key: ```python for i, arg in enumerate(args): if arg == "--provider" and i + 1 < len(args): provider_id = args[i + 1] elif arg == "--api-key" and i + 1 < len(args): api_key = args[i + 1] elif arg == "--model" and i + 1 < len(args): model_ids.append(args[i + 1]) if not provider_id: print("❌ --provider is required", file=sys.stderr) sys.exit(1) if not api_key: print("❌ --api-key is required", file=sys.stderr) sys.exit(1) patch = generate_patch(provider_id, api_key, model_ids or None) if patch: print(json.dumps(patch, indent=2, ensure_ascii=False)) ``` The documented workflow explicitly encourages users to place the secret in a command-line argument: ```bash python <skill-dir>/scripts/setup_model.py --provider deepseek --api-key sk-xxx ``` ### Technical Analysis API keys are authentication credentials and should not be exposed through process arguments, visible terminal entry, or routine output. Passing a key through `--api-key` can persist it in shell history. Depending on the operating system and process isolation settings, it may also be visible to process-monitoring utilities, diagnostic too ...[truncated 2298 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Remove command-line secret handling by default** - Deprecate `--api-key <value>`. - Accept the key through a protected environment variable, standard input, an inherited file descriptor, or an operating-system credential store. - If compatibility requires the option temporarily, display a prominent warning that it can expose the key through shell history and process inspection. 2. **Conceal interactive credential entry** - Replace ordinary terminal input with hidden input: ```python from getpass import getpass api_key = getpass("Enter API key: ").strip() ``` 3. **Do not print complete credentials** - Avoid emitting a patch containing the real `apiKey` to standard output. - Pass the patch directly to the trusted configuration API through an in-memory channel where supported. - If output is necessary, print a redacted representation such as `"apiKey": "********"` and provide the secret separately through a protected channel. 4. **Reduce accidental logging** - Ensure errors and debug output never include the key. - Document that generated configuration and transcripts are sensitive. - Disable or sanitize command tracing and application logging around secret processing. 5. **Update documentation** - Replace examples using `--api-key sk-xxx` with a secure workflow. - Explain the risks of shell history, process arguments, terminal scrollback, redirected output, and agent transcripts. - Do not imply that encrypted storage protects credentials before they reach the storage layer. 6. **Operational response** - Advise users who have already used the existing workflow to inspect and remove affected shell history and logs where feasible. - Rotate any API key that may have appeared in process arguments, terminal recordings, generated output, or agent transcripts. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (13)

Vague Triggers

Medium
Confidence
95% confidence
Finding
The manifest-style description lists specific trigger phrases but then broadens scope to '或任何国内 AI 模型接入相关需求' ('or any domestic AI model integration related need'). That catch-all condition is ambiguous and lacks clear boundaries, increasing the chance of unintended invocation for general discussion rather than explicit configuration requests.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This markdown file presents all instructions and configuration guidance only in Chinese, beginning with the title and continuing throughout the document. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is clearly documented and justified.

External Transmission

Medium
Category
Data Exfiltration
Content
PROVIDERS = {
    "deepseek": {
        "name": "DeepSeek",
        "base_url": "https://api.deepseek.com/v1",
        "api": "openai-completions",
        "models": [
            {"id": "deepseek-chat", "name": "DeepSeek Chat", "reasoning": False, "input": ["text"], "contextWindow": 65536, "maxTokens": 8192},
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
PROVIDERS = {
    "deepseek": {
        "name": "DeepSeek",
        "base_url": "https://api.deepseek.com/v1",
        "api": "openai-completions",
        "models": [
            {"id": "deepseek-chat", "name": "DeepSeek Chat", "reasoning": False, "input": ["text"], "contextWindow": 65536, "maxTokens": 8192},
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
PROVIDERS = {
    "deepseek": {
        "name": "DeepSeek",
        "base_url": "https://api.deepseek.com/v1",
        "api": "openai-completions",
        "models": [
            {"id": "deepseek-chat", "name": "DeepSeek Chat", "reasoning": False, "input": ["text"], "contextWindow": 65536, "maxTokens": 8192},
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
},
    "moonshot": {
        "name": "Moonshot (Kimi)",
        "base_url": "https://api.moonshot.cn/v1",
        "api": "openai-completions",
        "models": [
            {"id": "moonshot-v1-8k", "name": "Moonshot v1 8K", "reasoning": False, "input": ["text"], "contextWindow": 8192, "maxTokens": 4096},
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
},
    "moonshot": {
        "name": "Moonshot (Kimi)",
        "base_url": "https://api.moonshot.cn/v1",
        "api": "openai-completions",
        "models": [
            {"id": "moonshot-v1-8k", "name": "Moonshot v1 8K", "reasoning": False, "input": ["text"], "contextWindow": 8192, "maxTokens": 4096},
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
},
    "baichuan": {
        "name": "百川 (Baichuan)",
        "base_url": "https://api.baichuan-ai.com/v1",
        "api": "openai-completions",
        "models": [
            {"id": "Baichuan3-Turbo", "name": "Baichuan3 Turbo", "reasoning": False, "input": ["text"], "contextWindow": 32768, "maxTokens": 4096},
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
},
    "baichuan": {
        "name": "百川 (Baichuan)",
        "base_url": "https://api.baichuan-ai.com/v1",
        "api": "openai-completions",
        "models": [
            {"id": "Baichuan3-Turbo", "name": "Baichuan3 Turbo", "reasoning": False, "input": ["text"], "contextWindow": 32768, "maxTokens": 4096},
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
},
    "lingyiwanwu": {
        "name": "零一万物 (Yi)",
        "base_url": "https://api.lingyiwanwu.com/v1",
        "api": "openai-completions",
        "models": [
            {"id": "yi-medium", "name": "Yi Medium", "reasoning": False, "input": ["text"], "contextWindow": 16384, "maxTokens": 4096},
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
},
    "lingyiwanwu": {
        "name": "零一万物 (Yi)",
        "base_url": "https://api.lingyiwanwu.com/v1",
        "api": "openai-completions",
        "models": [
            {"id": "yi-medium", "name": "Yi Medium", "reasoning": False, "input": ["text"], "contextWindow": 16384, "maxTokens": 4096},
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The script accepts an API key and prints it back inside the generated config JSON to stdout without masking, secure prompting, or an explicit warning that the credential will be exposed in terminal history, logs, screenshots, or calling-agent transcripts. In an agent skill context, stdout is often captured automatically, which makes secret disclosure more likely than in a purely local manual workflow.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
The file explicitly brands itself as configuring Chinese model providers and presents several user-facing strings only in Chinese or mixed Chinese/English. This imposes a locale-specific experience without any opt-in or documented justification in the file itself.

Static analysis

No suspicious patterns detected.