Back to skill

Security audit

Model Switch

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its model-switching purpose, but it persists provider API keys into local OpenClaw config and every agent auth profile, which needs user review before installation.

Install only if you are comfortable with this tool changing your OpenClaw model defaults and writing provider API keys to local JSON config files for all agents. Prefer backing up ~/.openclaw first, use least-privilege API keys, check file permissions after add-key, and rotate keys if those files may have been exposed.

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
model_switcher.py:424
Finding

Provider API Keys Persisted and Duplicated in Plaintext

Content
View full analysis

Vulnerability Details

File Location: model_switcher.py, lines 424-451
Vulnerability Type: Plaintext storage and duplication of sensitive credentials
Risk Level: Medium

Vulnerable Code

python
env_val = os.environ.get(env_key, "")
if not env_val:
    print(f"   ❌ Environment variable {env_key} is not set")
    sys.exit(1)

cfg = load_config()
if provider not in cfg.get("models", {}).get("providers", {}):
    cfg.setdefault("models", {}).setdefault("providers", {})[provider] = {}

cfg["models"]["providers"][provider]["apiKey"] = env_val
save_config(cfg)
print(f"   ✅ Added to models.providers.{provider}.apiKey")

# Also update every agent's auth profile
for agent in cfg.get("agents", {}).get("list", []):
    aid = agent["id"]
    apf_path = HOME / ".openclaw" / "agents" / aid / "agent" / "auth-profiles.json"
    if apf_path.exists():
        with open(apf_path) as f:
            apf = json.load(f)
        profile = f"{provider}:default"
        apf.setdefault("profiles", {})[profile] = {
            "type": "api_key",
            "provider": provider,
            "key": env_val
        }
        _atomic_write_json(apf_path, apf)
        print(f"   ✅ {aid}: auth-profiles updated")

The relevant configuration writer does not enforce restrictive permissions:

python
def save_config(cfg):
    with open(CONFIG_PATH, "w") as f:
        json.dump(cfg, f, indent=2, ensure_ascii=False)

Technical Analysis

The add-key command reads an API credential from an environment variable and writes its plaintext value into ~/.openclaw/openclaw.json. It then duplicates the same credential into every existing agent's auth-profiles.json.

Neither save_config() nor _atomic_write_json() explicitly applies a restrictive file mode, validates file ownership, or rejects symbolic links. The resulting confidentiality therefore depends on the permissions of existing f ...[truncated 1530 chars]

Remediation
View remediation

Remediation Suggestions

  1. Prefer storing environment-variable references or secret-manager identifiers instead of copying credential values into JSON.
  2. If plaintext persistence is required by OpenClaw, minimize duplication and maintain one protected credential source rather than copying the key into every agent profile.
  3. Create credential-bearing files with mode 0600 and ensure containing directories are accessible only to the owning user.
  4. Before reading or replacing a file, verify that it is a regular file owned by the expected user and reject symbolic links.
  5. Preserve or explicitly harden permissions during atomic replacement. Create the temporary file with restrictive permissions and use an atomic same-filesystem replacement.
  6. Audit backup, diagnostic, logging, and support-bundle workflows to ensure these configuration files are excluded or redacted.
  7. Document secure credential rotation and remove all duplicated copies when a key is revoked.
  8. Add automated tests that verify restrictive permissions, symlink rejection, and the absence of credentials in command output.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (8)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The code performs credential discovery by checking both environment variables and stored config for provider API keys, then uses that information to decide whether credentials are 'ready'. While not exfiltrating secrets directly, this introduces secret-handling and inventory behavior into a tool whose advertised purpose is model switching, increasing the blast radius and normalizing credential propagation logic in an unrelated utility.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The add-key flow reads API keys from environment variables and persists them into ~/.openclaw/openclaw.json and each agent's auth-profiles.json. Persisting secrets to multiple files materially expands secret exposure through local file disclosure, backups, logs, sync tools, or weaker file permissions, and this behavior exceeds what users would reasonably expect from a model-switching utility.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

API key values are written verbatim into persistent configuration and per-agent auth files, but the user-facing output does not clearly disclose that secrets will be stored on disk and replicated across agents. This creates a significant confidentiality risk because compromise of any one of those files can disclose usable provider credentials.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documented switch, add, remove, and reset flows modify multiple configuration locations (openclaw.json, agent auth profiles, defaults) but the skill does not clearly warn that these operations overwrite existing model and authentication settings. Users may assume these are temporary or session-scoped actions, causing unintended configuration drift, service disruption, or rollback difficulty.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill explicitly instructs users to run an add-key command that copies provider API keys from environment variables into persistent configuration, but it does not warn that this changes local config state and may store secrets in plaintext or broadly readable files. That omission can lead users to unintentionally persist sensitive credentials and expand their exposure surface beyond the original environment variable scope.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This shell file presents its descriptive comments and usage examples in Chinese only, with no indication that another language is available. Under the policy, language constraints should offer user choice or be explicitly justified; neither is present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The module docstring presents the tool description, commands, and trigger wording only in Chinese, effectively forcing a specific language for users reading built-in help. Under the policy, language constraints should be optional or explicitly justified rather than imposed without opt-in.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.