T09 · Insecure Skill Coding Practices
- Location
src/index.ts:224- Finding
Unauthenticated Webhook Allows Forged Messages to Be Injected into OpenClaw Sessions
- Content
View full analysis
{ try { const body = req.body as BitchatInboundMessage; if (!body || !body.senderPeerID || !body.text) { res.status(400).json({ error: 'Invalid message format' }); return; } const cfg = api.config as Record; const config = resolveConfig(cfg); if (!isSenderAllowed(config, body.senderPeerID)) { res.status(403).json({ error: 'Sender not allowed' }); return; } await api.injectMessage({ channel: 'bitchat', senderId: body.senderPeerID, senderName: body.senderNickname, text: body.text, messageId: body.messageId, chatType: body.type === 'direct' ? 'direct' : 'group', timestamp: body.timestamp, }); res.json({ ok: true }); } catch (err) { logger.error('[bitchat] Webhook error:', err); res.status(500).json({ error: 'Internal error' }); } }, }); ``` The default policy also accepts every supplied peer identifier: ```ts const DEFAULT_CONFIG: Required = { enabled: true, nickname: 'openclaw', bridgeUrl: 'http://localhost:3939', webhookPath: '/bitchat-webhook', autoStart: false, dmPolicy: 'open', allowFrom: [], }; ``` ### Technical Analysis The webhook accepts attacker-controlled message objects and passes their contents directly to `api.injectMessage`. It does not authenticate the bridge, verify a message signature, validate an authorization token, restrict the request origin, or provide replay protection. The limited validation only establishes that `senderPeerID` and `text` are truthy. It does not prove that the request came from ...[truncated 2379 chars]- Remediation
View remediation
