Back to skill

Security audit

Api Model list updater

Security checks for vulnerabilities and agentic risk

Overview

This skill has a legitimate model-catalog purpose, but it can send local or environment-backed API credentials to arbitrary configured provider URLs without destination validation.

Review each provider baseUrl before using this skill, especially entries using env: API keys. Avoid running it against untrusted, plaintext HTTP, private-network, or recently changed provider URLs unless you are sure no sensitive credential will be sent there. Expect it to modify OpenClaw model defaults after you select models, although it creates a backup first.

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

Error
Location
scripts/model-catalog-updater.py:46
Finding
API Credential Disclosure and SSRF Through Unvalidated Provider Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/model-catalog-updater.py`, lines 46–74 **Vulnerability Type**: Unvalidated outbound request with sensitive authorization data **Risk Level**: High ### Vulnerable Code ```python def get_providers(config): """Extract provider info from config.""" providers = config.get("models", {}).get("providers", {}) result = [] for name, data in providers.items(): base_url = data.get("baseUrl", "unknown") api_key = data.get("apiKey", "") result.append({ "name": name, "baseUrl": base_url, "apiKey": api_key, "api": data.get("api", "openai-completions") }) return result def fetch_models(provider): """Fetch models from provider's /v1/models endpoint.""" base_url = provider["baseUrl"].rstrip("/") api_key = provider["apiKey"] # Build auth header based on key type if api_key.startswith("env:"): import os env_var = api_key[4:] api_key = os.environ.get(env_var, "") headers = {"Accept": "application/json"} if api_key and api_key not in ["lmstudio", "qwen-oauth", "minimax-oauth"]: headers["Authorization"] = f"Bearer {api_key}" url = f"{base_url}/models" try: req = Request(url, headers=headers) with urlopen(req, timeout=30) as response: ``` ### Technical Analysis The script reads both `baseUrl` and `apiKey` from the local OpenClaw configuration and constructs an outbound request without validating the URL scheme, normalized hostname, port, resolved address, or trust relationship between the endpoint and credential. An `env:` API-key reference is resolved into the actual environment-variable value before the request is made. The resulting secret is then placed in the `Authorization` header for most providers. Consequently, a provider configured with an attacker-controlled URL causes the script to disclose the credential ...[truncated 2485 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Restrict URL schemes** - Require HTTPS for credential-bearing remote requests. - Permit HTTP only for explicitly approved loopback development endpoints. - Reject unsupported schemes, embedded URL credentials, malformed hosts, and ambiguous URLs. 2. **Validate destinations** - Normalize and parse the URL with `urllib.parse.urlsplit`. - Maintain an allowlist of trusted provider hostnames where feasible. - Resolve destination addresses and reject loopback, link-local, multicast, reserved, and private ranges unless the user has explicitly enabled local-provider access. - Revalidate after DNS resolution to reduce DNS-rebinding risk. 3. **Control redirects** - Disable automatic redirects or validate every redirect destination. - Never forward an `Authorization` header when the scheme, hostname, or port changes. - Reject HTTPS-to-HTTP downgrade redirects. 4. **Bind credentials to trusted providers** - Associate each credential with an expected hostname or provider identifier. - Do not attach a token merely because an arbitrary provider entry contains both a URL and key. - Require explicit confirmation before sending credentials to a new or changed origin. 5. **Reduce credential privileges** - Prefer short-lived, narrowly scoped tokens. - Avoid broad account-level keys where model-listing-only credentials are available. - Keep environment-backed secrets out of logs and error messages. 6. **Harden local-provider support** - Treat unauthenticated local services as a separate provider mode. - Do not send cloud-provider credentials to local endpoints. - Require an explicit configuration flag for private-network access. 7. **Fail securely** - Reject missing or invalid URLs instead of using the placeholder value `"unknown"`. - Display the normalized destination and whether authorization will be sent before making the request. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill describes capabilities that read configuration, write backups and updated config files, and query provider endpoints, but it declares no explicit tool scope or permissions. That mismatch increases the chance the runtime grants broader-than-necessary access, making unintended file modification or network use harder to constrain and review.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The natural-language triggers are broad phrases like 'show me available models' and 'what models are on lmstudio', which can overlap with ordinary conversation and accidentally invoke the skill. Because the skill performs network queries and edits configuration files, accidental activation could lead to unintended external requests and persistent config changes.

External Transmission

Medium
Category
Data Exfiltration
Content
Your configured providers:
1. qwen-portal (https://portal.qwen.ai/v1)
2. lmstudio (http://192.168.56.1:1234/v1)
3. xai (https://api.x.ai/v1)
4. openrouter (https://openrouter.ai/api/v1)
5. modal-direct (https://api.us-west-2.modal.direct/v1)
6. cloudflare-ai-gateway
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
2. lmstudio (http://192.168.56.1:1234/v1)
3. xai (https://api.x.ai/v1)
4. openrouter (https://openrouter.ai/api/v1)
5. modal-direct (https://api.us-west-2.modal.direct/v1)
6. cloudflare-ai-gateway
7. minimax
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.