Back to skill

Security audit

Openclaw Model Switch

Security checks for vulnerabilities and agentic risk

Overview

This is a local OpenClaw model-configuration helper; its config edits, API key storage, and gateway restart are disclosed and aligned with that purpose, though users should treat the credential handling carefully.

Before installing, understand that this skill can change your OpenClaw model configuration, save provider API keys in plaintext in ~/.openclaw/openclaw.json, and restart the OpenClaw gateway. Use it only on an account where that local config storage is acceptable, set the config file to owner-only permissions, and be cautious about following the optional unpinned npx recommendations for other skills.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/add-model-guide.py:199
Finding
API Keys Are Echoed and Stored Without Enforced Owner-Only Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/add-model-guide.py`, lines 119 and 199-218 **Vulnerability Type**: Plaintext credential handling and insecure file permissions **Risk Level**: Medium ### Vulnerable Code ```python api_key = input(f"{Colors.YELLOW}请输入 API Key(回车跳过):{Colors.NC} ").strip() ``` ```python def save_json(path, data): with open(path, 'w', encoding='utf-8') as f: json.dump(data, f, indent=2, ensure_ascii=False) ``` ```python # Update openclaw.json if API key provided if api_key: openclaw = load_json(OPENCLAW_CONFIG) if OPENCLAW_CONFIG.exists() else {} if 'models' not in openclaw: openclaw['models'] = {'mode': 'merge', 'providers': {}} if 'providers' not in openclaw['models']: openclaw['models']['providers'] = {} provider_id = provider['id'] if provider_id not in openclaw['models']['providers']: openclaw['models']['providers'][provider_id] = { 'baseUrl': f"https://api.{provider_id}.com/v1" if provider_id != 'custom' else "", 'apiKey': api_key, 'api': 'openai-completions', 'models': [] } else: openclaw['models']['providers'][provider_id]['apiKey'] = api_key save_json(OPENCLAW_CONFIG, openclaw) ``` ### Technical Analysis The script obtains an API key through the standard `input()` function. Terminal input is therefore visible while the user types it and may be captured through shoulder surfing, terminal recording, or other session-monitoring mechanisms. The key is then stored in plaintext in `~/.openclaw/openclaw.json`. The generic `save_json()` function opens the destination using normal process defaults and does not explicitly create the file with mode `0600` or verify its permissions after writing. When the file is newly created, its resulting permissions depend on the user's process umask. A common umask can produce a file readable by other local users. The documentation warns that keys a ...[truncated 1277 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Read credentials with `getpass.getpass()` so they are not echoed: ```python from getpass import getpass api_key = getpass("Enter API Key: ").strip() ``` 2. Create the configuration with owner-only permissions: ```python import os fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600) with os.fdopen(fd, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) ``` 3. Explicitly enforce `0600` after writing, including when updating an existing file: ```python os.chmod(path, 0o600) ``` 4. Write to an owner-only temporary file and atomically replace the destination to avoid partially written configuration data. 5. Prefer an operating-system credential store, dedicated secret manager, or environment-variable reference instead of embedding the API key directly in JSON. 6. Detect unsafe existing permissions and either correct them automatically or stop with a clear warning before writing the secret. ]]>

T08 · Insecure Dependencies

Note
Location
README.md:36
Finding
Documentation Recommends Unpinned Third-Party Package Execution<![CDATA[ ## Vulnerability Details **File Location**: `README.md`, lines 36-40 **Vulnerability Type**: Unpinned third-party dependency and supply-chain exposure **Risk Level**: Low ### Vulnerable Code ```bash npx clawhub install openclaw-auto-backup npx clawhub install openclaw-search-pro npx clawhub install openclaw-memory-enhancer ``` ### Technical Analysis The documentation recommends installing three unrelated third-party components through `npx` without pinning reviewed versions or providing integrity hashes. Their source code is not included in this project and was therefore outside the auditable package. Because the commands resolve mutable package content, the code executed or installed when a user follows these instructions can differ from the code that existed when this skill was reviewed. A compromised registry account, malicious release, package replacement, or upstream compromise could consequently introduce attacker-controlled code. The commands are documentation recommendations rather than code automatically executed by this project, so exploitation requires a user to follow the optional instructions. ### Attack Path 1. An attacker compromises one of the recommended package names, its publisher account, or its distribution source. 2. The attacker publishes a malicious release under the same package identity. 3. A user follows the README's recommended installation commands. 4. `npx` resolves the current unpinned package or installer content. 5. Malicious install-time or runtime code executes with the invoking user's privileges. 6. The payload can access files, credentials, and services available to that user. ### Impact Assessment Potential impact depends entirely on the behavior of a compromised dependency and the privileges of the user running `npx`. At maximum, malicious package code could read or modify user-accessible files, steal credentials, alter OpenClaw configuration, or execute additional commands under the user's account. No ...[truncated 221 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove unrelated package recommendations unless they are necessary for this skill. 2. Pin each dependency or installer to a specific reviewed version rather than resolving the latest release. 3. Provide cryptographic integrity hashes or equivalent registry lockfile integrity metadata. 4. Identify the authoritative registry and source repository for every recommended package. 5. Require users to inspect the package source, permissions, and lifecycle scripts before installation. 6. Avoid instructions that execute remotely resolved package content directly; use a reviewed and reproducible installation process instead. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (25)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The Chinese-language description similarly overclaims capabilities such as adding models, natural-language switching, one-click API key configuration, and intelligent model inference that are reportedly not present. Multilingual overstatement broadens the risk by misleading a wider set of users into exposing secrets or relying on nonexistent safeguards during configuration changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The Chinese-language description similarly overclaims capabilities such as adding models, natural-language switching, one-click API key configuration, and intelligent model inference that are reportedly not present. Multilingual overstatement broadens the risk by misleading a wider set of users into exposing secrets or relying on nonexistent safeguards during configuration changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The Chinese-language description similarly overclaims capabilities such as adding models, natural-language switching, one-click API key configuration, and intelligent model inference that are reportedly not present. Multilingual overstatement broadens the risk by misleading a wider set of users into exposing secrets or relying on nonexistent safeguards during configuration changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The Chinese-language description similarly overclaims capabilities such as adding models, natural-language switching, one-click API key configuration, and intelligent model inference that are reportedly not present. Multilingual overstatement broadens the risk by misleading a wider set of users into exposing secrets or relying on nonexistent safeguards during configuration changes.

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Content
def restart_gateway():
    log_info("重启网关中...")
    os.system('openclaw gateway restart > /dev/null 2>&1')
    time.sleep(3)
    for i in range(10):
        result = subprocess.run(['openclaw', 'gateway', 'status'],
Confidence
85% confidence
Finding
os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The document is predominantly written in Chinese and presents the usage and safety guidance in that language, while only providing an "English Version" self-link rather than an actual alternate-language option. This can violate language/locale policy because the skill documentation effectively forces one language without user opt-in or a documented regional justification.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The feature description uses natural-language triggers like "use gemini" and "切换到千问" without clarifying whether these are the exact invocation phrases, examples only, or constrained to a specific command interface. Because one example is a short everyday-style phrase in English, the README lacks specificity about trigger scope and exclusion conditions.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
The README advertises 'Auto-configure API keys', which implies access to or modification of sensitive credentials. Although the file later says not to provide sensitive information, it does not clearly warn users that the skill may handle API keys or explain the associated privacy and security implications.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill documentation describes capabilities that read and write local configuration files and invoke shell commands, but it declares no explicit tool scope such as permissions or allowed-tools. This creates an authorization gap where consumers cannot easily assess or constrain the skill's operational reach before use, increasing the chance of unintended file modification or command execution.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**API Key 存储方式:**
- **位置:** `~/.openclaw/openclaw.json`
- **格式:** 明文存储(未加密)
- **权限:** 取决于文件权限(建议 `chmod 600`)

**安全建议:**
1. 备份配置文件:`cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak`
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**API Key 存储方式:**
- **位置:** `~/.openclaw/openclaw.json`
- **格式:** 明文存储(未加密)
- **权限:** 取决于文件权限(建议 `chmod 600`)

**安全建议:**
1. 备份配置文件:`cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak`
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**API Key 存储方式:**
- **位置:** `~/.openclaw/openclaw.json`
- **格式:** 明文存储(未加密)
- **权限:** 取决于文件权限(建议 `chmod 600`)

**安全建议:**
1. 备份配置文件:`cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak`
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**API Key 存储方式:**
- **位置:** `~/.openclaw/openclaw.json`
- **格式:** 明文存储(未加密)
- **权限:** 取决于文件权限(建议 `chmod 600`)

**安全建议:**
1. 备份配置文件:`cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak`
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The alias "flash" is overly generic and can easily collide with ordinary user language or other model naming conventions, causing the wrong model to be selected. In a skill that performs natural-language model switching, ambiguous aliases directly affect routing behavior and can silently change provider, capabilities, cost, or data-handling characteristics.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
Most interactive prompts and status messages are presented only in Chinese, which imposes a specific language on all users. The file does not provide a language selection mechanism or explain that the tool is intentionally limited to a Chinese-speaking context.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The script accepts an API key interactively and writes it into ~/.openclaw/openclaw.json without an explicit warning, consent flow, or permission hardening. Storing long-lived credentials in plaintext on disk increases exposure to local compromise, backups, other tooling, or accidental disclosure, especially in a model-switching skill that is specifically designed to manage provider secrets.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
switch_script = SCRIPT_DIR / "switch-model.py"
            if switch_script.exists():
                import subprocess
                subprocess.run(['python3', str(switch_script), model_key])
            else:
                print(f"{Colors.YELLOW}⚠️  switch-model.py 不存在,请手动切换{Colors.NC}")
        else:
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This code presents all user-facing messages in Chinese, including headers, status labels, and descriptions. That forces a specific language for all users without any opt-in, fallback, or documented regional justification, which matches the language/locale policy violation criteria.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
os.system('openclaw gateway restart > /dev/null 2>&1')
    time.sleep(3)
    for i in range(10):
        result = subprocess.run(['openclaw', 'gateway', 'status'], 
                               stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
        if 'running' in result.stdout.lower():
            log_success("网关已重启完成")
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
The file includes a link to a Chinese version, which indicates multilingual support exists, but it does not itself force a single language or locale. Because users are given an English README here and can navigate to another language version, this is only a weak signal and likely not a violation.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
The user-facing messages at L26, L30, L33, L37-L42, and L44 are written only in Chinese. Per the policy, forcing a specific language without user opt-in or justification is a natural-language policy violation.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The script's status messages, warnings, and usage/help text are presented in Chinese throughout the file. This imposes a specific language on all users without any opt-in, selection mechanism, or documentation that the skill is intentionally limited to a Chinese-speaking context.

Static analysis

No suspicious patterns detected.