Back to skill

Security audit

openclaw-fallback-skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a cloud-model fallback helper, but it appears to send conversations to the configured API far more often than disclosed and includes a secret-shaped API key in its package.

Review this carefully before installing. Use only a trusted endpoint, rotate or remove the packaged API-key-shaped value, and do not enable the skill for sensitive conversations unless the fallback bug is fixed, metadata forwarding is removed or minimized, and remote transfers are clearly logged or gated by user/admin consent.

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

Error
Location
index.js:65
Finding
Unconditional Transmission of User Messages, Conversation History, and Metadata<![CDATA[ ## Vulnerability Details **File Location**: `index.js:65-98`, `index.js:104-120`, and `index.js:242-250` **Vulnerability Type**: Unintended sensitive-data disclosure caused by incorrect fallback logic **Risk Level**: High ### Vulnerable Code ```js shouldFallback(response, confidence) { // Scenario 1: confidence is too low if (confidence && confidence < this.config.fallbackThreshold) { return true; } // Scenario 2: response is empty or too short if (!response || response.length < 10) { return true; } // Scenario 3: response contains an inability-to-answer keyword const unableKeywords = [ '无法回答', '不能回答', '不知道', 'not sure', "i don't know", "can't answer", "unable to" ]; const lowerResponse = response.toLowerCase(); if (unableKeywords.some(keyword => lowerResponse.includes(keyword))) { return true; } // Scenario 4: response is overly generic const genericPatterns = [ /^这是一个好问题/, /^that's a good question/, /^i understand/ ]; if (genericPatterns.some(pattern => pattern.test(response))) { return true; } return true; } ``` The data sent after the unconditional fallback decision includes the current message and recent conversation history: ```js async getCloudResponse(userMessage, context) { const sessionId = context.sessionId || 'default'; // Retrieve conversation history let history = this.conversationHistory.get(sessionId) || []; // Build the remote model message list const messages = [ { role: 'system', content: this.buildSystemPrompt(context) }, ...history.slice(-10), { role: 'user', content: userMessage } ]; ``` Optional user metadata is also incorporated into the remote system prompt: ```js buildSystemPrompt(context) { const basePrompt = `你是一个智能助手,正在帮助用户解决问题。 请提供准确、详细、有帮助的回答。 如果问题涉及实时信息或你不确定的内容,请诚实说明。`; if (context.metadata && context.metadata.userInfo) { return `${basePrompt}\n\n用户信息: ${JSON.stringify(co ...[truncated 2324 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the unconditional final return with a negative result: ```js return false; ``` 2. Require an explicit fallback condition before constructing or transmitting a cloud request. 3. Exclude `metadata.userInfo` by default. If it is operationally necessary, use an explicit allowlist of required fields and obtain informed user consent. 4. Provide a clear disclosure identifying what data is sent, to which service, and under which conditions. 5. Permit only HTTPS endpoints except for explicitly approved loopback development addresses. 6. Validate `apiUrl` against an administrator-controlled allowlist to reduce arbitrary data-exfiltration destinations. 7. Use a cryptographically strong, per-session identifier and reject missing session identifiers in multi-user deployments rather than using the shared `"default"` history bucket. 8. Add automated tests confirming that adequate local responses produce `false` and do not result in outbound requests. 9. Add retention limits and explicit cleanup policies for conversation history. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
config.json:3
Finding
Hard-Coded API Credential in Distributed Configuration<![CDATA[ ## Vulnerability Details **File Location**: `config.json:3` **Vulnerability Type**: Hard-coded secret **Risk Level**: High ### Vulnerable Code ```json { "apiUrl": "http://localhost:13000/v1/chat/completions", "apiKey": "sk-6cbc43a72af3312b25babf8c008989465ed15f4049990605", "modelName": "deepseek-v3.2", "fallbackThreshold": 0.5, "maxRetries": 3, "timeout": 60, "enableStreaming": true } ``` ### Technical Analysis `config.json` contains a complete secret-shaped API credential rather than a placeholder. Any person or process with access to the project package, source archive, repository history, build artifact, or backup can recover it. Static analysis cannot establish whether the credential is currently active or what service accepts it. Nevertheless, committing an operational-looking credential is an insecure secret-management practice. Deleting it only from the current file would also be insufficient if it has already entered repository history or distributed artifacts. The configured endpoint uses plaintext HTTP. It currently points to a loopback address, which limits network interception under the shown configuration, but the implementation does not enforce this restriction if the endpoint is later changed to a non-loopback host. ### Attack Path 1. An attacker obtains a copy of the project, published skill package, repository history, backup, or deployment artifact. 2. The attacker reads `config.json`. 3. The attacker extracts the API credential. 4. The attacker identifies or guesses a compatible API service for the credential. 5. If the credential is valid and externally usable, the attacker submits unauthorized requests under the credential owner's account. 6. The resulting activity may consume quotas, create costs, expose associated account resources, or cause account suspension. ### Impact Assessment The exact privileges depend on the unknown permissions and validity of the exposed credential. Potential impact includes una ...[truncated 384 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Immediately revoke or rotate the exposed credential through the relevant provider. 2. Remove the credential from the current source tree, repository history, release archives, caches, backups, and previously published packages where feasible. 3. Replace `config.json` with a non-secret template containing a clearly invalid placeholder. 4. Load the credential at runtime from a protected environment variable, operating-system credential store, or managed secrets service. 5. Restrict secret-file permissions to the service account that requires access. 6. Add `config.json` and other local secret files to `.gitignore`, while retaining only `config.example.json`. 7. Enable automated secret scanning in local hooks and continuous-integration pipelines. 8. Apply least privilege, usage limits, expiration, endpoint restrictions, and rotation policies to replacement credentials. 9. Enforce HTTPS whenever the configured service is not a loopback development endpoint. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (15)

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly states it will automatically call a configured cloud LLM API when the local model cannot answer, and it requests both network and configuration permissions including an API key. That means user prompts or contextual data may leave the local environment without any user-facing notice, consent flow, data minimization, or disclosure of what is transmitted, which creates a real privacy and data-governance risk.

External Transmission

Medium
Category
Data Exfiltration
Content
{
  "apiUrl": "https://api.openai.com/v1/chat/completions",
  "apiKey": "sk-your-api-key-here",
  "modelName": "gpt-4",
  "fallbackThreshold": 0.6,
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The comment and docstring indicate this function determines whether fallback is needed based on several conditions, implying it may return either true or false. However, after checking the listed scenarios, the function unconditionally returns true at L098, so fallback is always triggered regardless of response quality or confidence.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill forwards user messages, recent conversation history, and a system prompt containing optional user metadata to an external cloud API without any explicit consent, notice, redaction, or policy gating. In this skill's context, the risk is amplified because the buggy fallback logic causes cloud transmission effectively all the time, turning a fallback path into continuous third-party data exfiltration.

Ssd 3

Medium
Confidence
95% confidence
Finding
The system prompt injects `context.metadata.userInfo` directly into model context as plain text, which can expose sensitive user attributes to the external model and increase the chance that private details are echoed back in responses, logs, or provider-side retention. In this skill, that danger is higher because the metadata is sent alongside user content to a third-party API and fallback is effectively always triggered.

Session Persistence

Medium
Category
Rogue Agent
Content
安装步骤:
创建技能目录
Copy
mkdir -p ~/.openclaw/skills/openclaw-fallback-skill
cd ~/.openclaw/skills/openclaw-fallback-skill
创建配置文件
Copy
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

External Transmission

Medium
Category
Data Exfiltration
Content
# 或直接重启你的 OpenClaw 进程
配置说明:
配置项	说明	示例
apiUrl	云端模型 API 地址	https://api.openai.com/v1/chat/completions
apiKey	API 密钥	sk-xxx
modelName	模型名称	gpt-4, claude-3-opus-20240229
fallbackThreshold	触发阈值(0-1)	0.6
Confidence
90% confidence
Finding
The documentation explicitly configures an external API endpoint for cloud inference, which creates a real external transmission path for user inputs and possibly contextual data. In this skill's context, that transmission is core functionality, but it is still security-relevant because it can expose sensitive information to third parties if not clearly disclosed and controlled.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The README instructs users to configure a cloud model API endpoint and API key, which implies user prompts and model interactions may be transmitted to a third-party service. It does not warn about privacy, data handling, retention, or compliance implications, so users may unknowingly send sensitive local data off-host.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documented automatic fallback behavior is designed to switch to a cloud model transparently when the local model performs poorly. Without a clear warning and consent mechanism, this can cause sensitive prompts or system context to be sent externally without the user's awareness, increasing privacy and operational risk.

External Transmission

Medium
Category
Data Exfiltration
Content
高级配置示例:
Copy
{
  "apiUrl": "https://api.deepseek.com/v1/chat/completions",
  "apiKey": "sk-deepseek-xxx",
  "modelName": "deepseek-chat",
  "fallbackThreshold": 0.5,
Confidence
90% confidence
Finding
The advanced example shows another third-party API endpoint, reinforcing that the skill supports sending content to external services. This is not inherently malicious, but in the absence of strong warnings and controls it can lead to unintentional disclosure of sensitive prompts, credentials, or local context.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The skill is designed to automatically send requests to a configured cloud LLM whenever the local model fails or confidence drops below a threshold, but the manifest does not document any constraints on what data may be forwarded, when fallback is allowed, or whether user consent/sanitization is required. In a beforeResponse/modelFailure context, this can cause unintended transmission of sensitive prompts, conversation history, or internal context to an external endpoint, making data exfiltration through normal operation more likely.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The natural-language description is presented only in Chinese and does not indicate any user-selectable language or region-specific justification. Under the language/locale policy, this can be a violation when a skill imposes a specific language without opt-in.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
The natural-language system prompt is written entirely in Chinese and instructs the assistant behavior in that locale, with no indication that users may choose another language. This can violate language/locale policy when a skill forces a specific language without opt-in or documented regional justification.

Natural-Language Policy Violations

Low
Confidence
72% confidence
Finding
All instructional text in the file is presented in Chinese, with no alternative language or note that the skill is intended for a Chinese-speaking audience. This can be a natural-language policy concern when a skill effectively forces a locale without opt-in or documented justification.

Natural-Language Policy Violations

Low
Confidence
85% confidence
Finding
The natural-language description and configuration field descriptions are written only in Chinese, which can impose a language expectation without offering user choice or documenting a justified locale restriction. Under the stated policy, language constraints should be optional or clearly justified.

Static analysis

No suspicious patterns detected.