T09 · Insecure Skill Coding Practices
- Location
test_models.py:14- Finding
Cross-Provider API Credential Disclosure
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill has a coherent model-update purpose, but it can expose the wrong API token and makes persistent live agent configuration and service changes with weak safeguards.
Review carefully before installing. Use only an OpenRouter-scoped API key, do not rely on ANTHROPIC_AUTH_TOKEN, back up ~/.claude/settings.json and ~/.openclaw/openclaw.json, avoid complete_test.sh on a live setup, inspect /tmp/verified_models.txt before applying, and confirm any OpenClaw restart manually.
test_models.py:14Cross-Provider API Credential Disclosure
fetch_models.py:67Predictable Shared Temporary Files Allow Symlink and Workflow-Result Manipulation
complete_test.sh:25Installation Test Mutates Live OpenClaw Configuration Without Explicit Confirmation
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
cd ~/.openclaw/workspace/skills/updating-openrouter-free-models
# Optional: clean old cache
rm -f /tmp/free_models.txt /tmp/verified_models.txt /tmp/failed_models.txt
# Run full update
python3 fetch_models.py && python3 test_models.py && node apply_updates_openclaw.js
# Restart
This documentation directs interaction with sensitive agent configuration paths under the user's home directory. In the context of an install/update skill, access to ~/.claude/settings.json and ~/.openclaw/openclaw.json is security-relevant because these files control model/provider behavior and can be altered to change agent operation or break service availability.
./restart_openclaw.sh
python3 -m json.tool ~/.claude/settings.json # Claude python3 -m json.tool ~/.openclaw/openclaw.json # OpenClaw
The skill’s declared purpose is configuration maintenance, but it also directs service management actions including restarting OpenClaw, interacting with launchctl, killing processes, and spawning background services. Hidden operational side effects increase risk because an agent or user may approve a config-update workflow without realizing it includes system-level process control.
The skill’s declared purpose is configuration maintenance, but it also directs service management actions including restarting OpenClaw, interacting with launchctl, killing processes, and spawning background services. Hidden operational side effects increase risk because an agent or user may approve a config-update workflow without realizing it includes system-level process control.
The skill targets ~/.claude/settings.json, a sensitive agent configuration file that influences model availability and behavior. Writing to agent config directories is security-relevant because it can persistently alter how the assistant operates, potentially causing denial of service, misrouting, or unsafe defaults if abused or performed incorrectly.
")
Then manually or programmatically insert into `~/.claude/settings.json`.
### Step 4: Update OpenClaw Configuration
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
return False, str(e)
def update_claude_settings(verified_models):
"""Update ~/.claude/settings.json with verified models."""
settings_path = Path.home() / '.claude' / 'settings.json'
if not settings_path.exists():
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
return False, str(e)
def update_claude_settings(verified_models):
"""Update ~/.claude/settings.json with verified models."""
settings_path = Path.home() / '.claude' / 'settings.json'
if not settings_path.exists():
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
return False, str(e)
def update_claude_settings(verified_models):
"""Update ~/.claude/settings.json with verified models."""
settings_path = Path.home() / '.claude' / 'settings.json'
if not settings_path.exists():
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
return False, str(e)
def update_claude_settings(verified_models):
"""Update ~/.claude/settings.json with verified models."""
settings_path = Path.home() / '.claude' / 'settings.json'
if not settings_path.exists():
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
return False, str(e)
def update_claude_settings(verified_models):
"""Update ~/.claude/settings.json with verified models."""
settings_path = Path.home() / '.claude' / 'settings.json'
if not settings_path.exists():
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
return False, str(e)
def update_claude_settings(verified_models):
"""Update ~/.claude/settings.json with verified models."""
settings_path = Path.home() / '.claude' / 'settings.json'
if not settings_path.exists():
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
return False, str(e)
def update_claude_settings(verified_models):
"""Update ~/.claude/settings.json with verified models."""
settings_path = Path.home() / '.claude' / 'settings.json'
if not settings_path.exists():
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
return False, str(e)
def update_claude_settings(verified_models):
"""Update ~/.claude/settings.json with verified models."""
settings_path = Path.home() / '.claude' / 'settings.json'
if not settings_path.exists():
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
return False, str(e)
def update_claude_settings(verified_models):
"""Update ~/.claude/settings.json with verified models."""
settings_path = Path.home() / '.claude' / 'settings.json'
if not settings_path.exists():
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
return False, str(e)
def update_claude_settings(verified_models):
"""Update ~/.claude/settings.json with verified models."""
settings_path = Path.home() / '.claude' / 'settings.json'
if not settings_path.exists():
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
return False, str(e)
def update_claude_settings(verified_models):
"""Update ~/.claude/settings.json with verified models."""
settings_path = Path.home() / '.claude' / 'settings.json'
if not settings_path.exists():
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
return False, str(e)
def update_claude_settings(verified_models):
"""Update ~/.claude/settings.json with verified models."""
settings_path = Path.home() / '.claude' / 'settings.json'
if not settings_path.exists():
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
return False, str(e)
def update_claude_settings(verified_models):
"""Update ~/.claude/settings.json with verified models."""
settings_path = Path.home() / '.claude' / 'settings.json'
if not settings_path.exists():
The documentation instructs users to apply configuration changes and restart a running service without an explicit warning that this modifies user state and may interrupt availability. In a skill context, this can lead to unintended downtime or accidental overwriting of a user's working configuration, especially if followed blindly or automated by an agent.
The one-command workflow hides several state-changing operations behind a single command, including testing, config modification, and restart behavior, without warning the user. This increases the risk that a user or agent executes it without understanding its side effects, causing unexpected service interruption or configuration drift.
The README prominently describes automated configuration changes and service restarts as core behavior but does not provide an upfront safety warning about modifying local agent config files and disrupting running services. In an agent-executed workflow, this can lead users or downstream agents to perform impactful actions without informed consent, increasing the chance of unintended local misconfiguration or service interruption.
The installation prompts are written for an AI agent and instruct it to create directories, copy files, change permissions, and execute scripts and tests, but they omit explicit warnings about filesystem writes, network access, and execution side effects. This is dangerous because agentic installers can perform these actions automatically, potentially altering user environments and running unreviewed code with little friction.
The skill clearly instructs use of shell commands, environment-based secrets, and reads/writes user configuration files, yet it declares no tool scope or permission boundary. This creates an overbroad execution surface where an agent may perform sensitive actions without explicit capability disclosure or user awareness.
The instructions modify ~/.claude/settings.json and ~/.openclaw/openclaw.json without clear backup, diff review, or confirmation guidance. Direct edits to agent configuration can break tooling, alter model routing, or persist unintended settings changes if the generated model list or update logic is wrong.
The script persistently overwrites agent configuration based on unvalidated content from /tmp/verified_models.txt, causing long-lived changes to future tool behavior. Because /tmp is a shared, world-writable location on many systems, another local process could tamper with that file and inject arbitrary model IDs into the user's Claude/OpenClaw config, leading to persistent misconfiguration or redirection to unintended providers/models.
config['model'] = primary
config['availableModels'] = verified_models
# Write with proper formatting
with open(settings_path, 'w') as f:
json.dump(config, f, indent=2)
f.write('\n')