T09 · Insecure Skill Coding Practices
Error
- Location
- src/router.js:15
- Finding
- Cloud fallback opt-out is ignored and raw queries bypass privacy sanitization<![CDATA[ ## Vulnerability Details **File Location**: `src/router.js:15-16, 45-56, 224-307`; `src/index.js:106-109, 173-179` **Vulnerability Type**: Privacy control bypass and unintended external data disclosure **Risk Level**: High ### Vulnerable Code ```javascript // src/router.js this.localFirst = this.config.localFirst !== false; this.localThreshold = this.config.localThreshold || 0.8; this.cloudFallback = this.config.cloudFallback !== false; ``` ```javascript // src/router.js if (!this.localFirst || !ollamaAvailable) { if (!cloudAvailable) { throw new Error('No inference provider available (Ollama down, no cloud API)'); } decision = { provider: 'cloud', model: this.selectCloudModel(), reasoning: 'Local unavailable or disabled' }; this.stats.cloudDecisions++; } else { decision = this.applyRoutingLogic(analysis); } ``` ```javascript // src/index.js if (decision.provider === 'local') { response = await this.executeLocal(query, context, decision.model); } else { // Strip context before sending to cloud const strippedContext = await this.contextStripper.strip(context, query); response = await this.executeCloud(query, strippedContext, decision.model); } ``` ```javascript // src/index.js async executeCloud(query, strippedContext, model) { const result = await this.openclaw.query(query, { model, context: strippedContext, provider: 'cloud' }); return { text: result.response, model, provider: 'cloud', tokens: result.tokens || {} }; } ``` ### Technical Analysis The router reads `cloudFallback`, but no routing branch enforces it. The configured value therefore has no effect on decisions made by `applyRoutingLogic()`. Token-count, complexity, domain-confidence, and hybrid routing can all return a cloud decision even when `cloudFallback` is explicitly set to `false`. The privacy layer only sanitizes the context object. The original `query` is passed unchanged to `openclaw.query()`. Conseque ...[truncated 1362 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Enforce the cloud opt-out immediately before every cloud call: ```javascript if (decision.provider !== 'local' && !this.config.routing?.cloudFallback) { decision = { provider: 'local', model: this.config.ollama?.bundledModel || 'qwen2.5:7b', reasoning: 'Cloud fallback disabled' }; } ``` 2. Add a second fail-closed check inside `executeCloud()` so routing defects cannot bypass policy. 3. Sanitize both the query and context before transmission. 4. Validate the final outbound payload rather than only the original context. 5. Treat `hybrid` as a distinct execution path with explicit local and optional cloud phases. 6. Require explicit user consent before sending a prompt identified as sensitive. 7. Add tests proving that no cloud API is invoked when `cloudFallback` is false. ]]>
