Back to skill

Security audit

OpenRouter Free Model Rotate

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but it can persistently rewrite OpenClaw model configuration, expose API keys through examples, and signal local gateway processes with limited safeguards.

Review before installing. Use OPENROUTER_API_KEY rather than putting keys on the command line or in cron, run --scan or --no-update first, back up OpenClaw config files before applying changes, and avoid --restart or scheduled auto-rotation unless you accept persistent model-routing changes and possible gateway reload disruption.

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

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:84
Finding

OpenRouter API Key Exposed Through Command-Line and Cron Examples

Content
View full analysis
/var/log/model-rotate.log 2>&1 ``` ```python # scripts/rotate_free_models.py:550-551 parser.add_argument("--api-key", default=os.environ.get("OPENROUTER_API_KEY"), help="OpenRouter API key") ``` The quick-start examples at `SKILL.md:28-46` likewise recommend passing the key directly with `--api-key`. ### Technical Analysis The Skill accepts the OpenRouter API key through a command-line option and repeatedly recommends that method in its documentation. Command-line secrets may be exposed through: - Process listings and process-inspection interfaces while the command is running. - Shell command history. - Monitoring, debugging, or endpoint-management software that records command lines. - Persistent crontab content and administrative backups. - Accidental copying of commands into logs, tickets, or terminal transcripts. The script already supports `OPENROUTER_API_KEY`, so embedding the credential in command arguments or crontab is not necessary for the declared functionality. Although the script only sends the Bearer token to the fixed OpenRouter HTTPS endpoint, its local method of receiving the token is insecure. ### Attack Path 1. A user follows the documented example and invokes the script with a live key: ```bash scripts/rotate_free_models.py --api-key "sk-or-live-key" --restart ``` 2. The complete command is retained in shell history, stored in crontab, or temporarily exposed through process metadata. 3. An attacker with access to the same account, readable operational records, backups, or ...[truncated 669 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/rotate_free_models.py:508
Finding

Broad Gateway Process Matching Can Signal Unintended Processes

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (7)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill advertises and instructs use of network access, file reads/writes, environment-secret handling, and shell execution, but it declares no explicit tool scope or permissions boundaries. In an agent environment, that means a caller may invoke a broadly capable workflow without clear least-privilege constraints, increasing the chance of unintended config modification, secret exposure, or command execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The quick-start section presents commands that update configuration and optionally restart a gateway as recommended usage before prominently warning about those side effects. This can lead users or agents to execute disruptive actions reflexively, causing downtime, broken routing, or accidental replacement of working model configuration.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/rotate_free_models.py (reported line 49)May include surrounding context.

python
def api_request(api_key, endpoint, body, timeout=30):
    """Generic POST to OpenRouter."""
    req_data = json.dumps(body).encode()
    req = __import__("urllib.request").request.Request(
        f"{API_BASE}/{endpoint}",
        data=req_data,
        headers={

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script modifies openclaw.json and models.json automatically unless --no-update is supplied, with no confirmation prompt, dry-run default, backup, or explicit upfront warning. In a security-sensitive agent environment, silent configuration mutation can redirect future model selection and persist unintended or harmful changes, especially if run with elevated privileges or automated triggers.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill goes beyond scanning and config updates by discovering local processes and sending SIGUSR1 to matching PIDs, including a broad pgrep -f openclaw-gateway fallback. This can affect unintended processes if names collide or if the runtime environment is shared, creating local integrity and availability risk through unauthorized process signaling.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/rotate_free_models.py (reported line 509)May include surrounding context.

python
# Fallback
    try:
        import subprocess
        result = subprocess.run(["pgrep", "-f", "openclaw-gateway"], capture_output=True, text=True)
        if result.returncode == 0:
            for pid in result.stdout.strip().split("\n"):
                os.kill(int(pid), signal.SIGUSR1)

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The code creates and writes persistent files under ~/.openclaw/state and optionally writes a JSON report to a user path. While the operations are visible in code, there is no general upfront disclosure that model test results and timestamps will be stored locally, which may matter for users expecting a read-only scan.

Content

No source excerpt is available for this finding.