T09 · Insecure Skill Coding Practices
- Location
index.ts:429- Finding
Fail-Open Initialization Race Allows Threat-Scanning Bypass
- Content
View full analysis
{ quarantine = mgr; }).catch(err => { api.logger.warn(`[hopeIDS] Quarantine init warning: ${err.message}`); }); ``` ```ts const record = await quarantine!.create({ ts: new Date().toISOString(), agent: agentId, source: event.source ?? 'unknown', senderId: event.senderId, intent: intent || 'unknown', risk, patterns, contentHash: hashContent(event.prompt), }); ``` ```ts } catch (err: any) { api.logger.warn(`[hopeIDS] Scan failed: ${err.message}`); } ``` ### Technical Analysis The quarantine manager is initialized asynchronously without being awaited before the `before_agent_start` scanning hook becomes operational. The TypeScript non-null assertion in `quarantine!.create(...)` suppresses compile-time null checks but provides no runtime protection. If a message reaches the block branch before initialization completes, `quarantine` remains `null`. Calling `create` then raises a runtime exception. The outer catch block merely logs the exception and returns no blocking response. The host can consequently continue normal agent processing. The same fail-open behavior applies to other exceptions raised during heuristic scanning, semantic classification, or quarantine storage. This contradicts the documented security invariant that a blocked message must be fully aborted. ### Attack Path 1. The OpenClaw process starts and registers the plugin. 2. Quarantine initialization begins asynchronously. 3. Before initialization completes, an attacker submits a malicious prompt that exceeds the blocking threshold. 4. The scan enters the blocking branch. 5. `quarantine!.create(...)` attempts to access the still-null manager and throws. 6. The catch block suppre ...[truncated 735 chars]- Remediation
View remediation
