Back to skill

Security audit

Free Models for OpenClaw and other Agents

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but it unnecessarily asks for and reads an OpenRouter API key that its code does not use.

Review before installing. The model discovery functionality is straightforward, but do not provide a live OpenRouter API key to this version unless you are comfortable with unnecessary credential exposure to the Node.js process. Prefer a version that removes the key requirement or clearly uses and scopes the key for authenticated functionality.

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

Note
Location
scripts/free-models.js:12
Finding
Unnecessary Collection and Requirement of an OpenRouter API Key<![CDATA[ ## Vulnerability Details **File Location**: `scripts/free-models.js:12`, `scripts/free-models.js:20-21`, `scripts/free-models.js:157-161`; `SKILL.md:68-74` **Vulnerability Type**: Unnecessary access to a sensitive environment variable and violation of least privilege **Risk Level**: Low ### Vulnerable Code `scripts/free-models.js:12`: ```js /** @type {string|null} */ const API_KEY = process.env.OPENROUTER_API_KEY || null; ``` `scripts/free-models.js:20-21`: ```js async function fetchAllModels() { const res = await fetch('https://openrouter.ai/api/v1/models'); ``` `scripts/free-models.js:157-161`: ```js async function main() { if (!API_KEY) { console.error('❌ Error: Set OPENROUTER_API_KEY environment variable'); console.error(' Example: export OPENROUTER_API_KEY="sk-or-v1-..."'); process.exit(1); } ``` `SKILL.md:68-74`: ```md User should register and get a access key from [https://openrouter.ai/settings/keys](https://openrouter.ai/settings/keys) Openclaw should export the key (or string with a prefix "sk-or-") as the value of Environment Variable `OPENROUTER_API_KEY` before calling the cli. ```bash export OPENROUTER_API_KEY="sk-or-v1-..." node scripts/free-models.js ``` ``` ### Technical Analysis The documentation instructs users to obtain and export a live OpenRouter API key. The CLI then reads that credential from the process environment and refuses to run without it. However, the only network request is a parameterless HTTPS GET request to the public OpenRouter models endpoint. The key is not added to an `Authorization` header, request body, query string, or any other outbound field. Consequently, access to the credential is not necessary for the Skill's declared model-discovery and filtering functionality. Requiring a sensitive credential when it is not used violates least-privilege principles and unnecessarily expands the sensitive data available to the Node.js process. The static pre-scan warning about sensitive ...[truncated 1657 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the unnecessary environment-variable read: ```js const API_KEY = process.env.OPENROUTER_API_KEY || null; ``` 2. Remove the API-key gate from `main()` so public model discovery works without credentials: ```js async function main() { console.log('🔍 Fetching models from OpenRouter...\n'); // Continue with public model discovery. } ``` 3. Remove the instructions in `SKILL.md` that ask users to obtain and export `OPENROUTER_API_KEY`. 4. If authenticated functionality is introduced later: - Request a credential only for operations that genuinely require authentication. - Read the key immediately before the authenticated request rather than at module initialization. - Send it only to the documented OpenRouter HTTPS origin using an authorization header. - Never place it in URLs, logs, error messages, or command-line arguments. - Validate the destination origin before attaching the authorization header. - Recommend a restricted, revocable key with the minimum available account privileges. 5. Add a test confirming that model discovery succeeds when `OPENROUTER_API_KEY` is absent. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Ae1

High
Category
analysis-evasion
Content
import { discoverFreeModels } from './scripts/free-models.js';
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
import { discoverFreeModels } from './scripts/free-models.js';
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
import { discoverFreeModels } from './scripts/free-models.js';
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
import { discoverFreeModels } from './scripts/free-models.js';
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
const models = await fetchAllModels();
  return models.filter((m) => {
    const promptPrice = parseFloat(m.pricing.prompt);
    return promptPrice === 0 || promptPrice < 0.0001;
  });
}
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Missing User Warnings

Low
Confidence
91% confidence
Finding
The README explicitly instructs users to place a live OpenRouter API key into an environment variable but gives no guidance on secure handling, scoping, rotation, or avoiding accidental disclosure in shell history, logs, screenshots, or shared environments. While using environment variables is common practice, documenting secret setup without basic safety warnings can lead to inadvertent credential exposure and downstream account misuse.

Intent-Code Divergence

Low
Confidence
96% confidence
Finding
The header comment and CLI check state that OPENROUTER_API_KEY is required, implying authenticated API usage. However, fetchAllModels performs an unauthenticated fetch to the models endpoint and no authorization header or API-key-based behavior appears anywhere in the code, so the documentation actively misstates what the code needs to do its core work.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/free-models.js:13