T05 · Unauthorized Access and Privilege Escalation
- Location
src/bot.ts:82- Finding
Pairing Policy Bypass and Unconditional Command Authorization
- Content
View full analysis
String(entry)); if (dmPolicy === "allowlist") { const allowed = allowFrom.some( (id) => id.toLowerCase() === ctx.userId.toLowerCase(), ); if (!allowed) { log(`wecom[${account.accountId}]: 用户 ${ctx.userId} 不在白名单中,忽略`); return; } } ``` ```ts const ctxPayload = core.channel.reply.finalizeInboundContext({ Body: body, RawBody: ctx.content, CommandBody: ctx.content, From: wecomFrom, To: wecomTo, SessionKey: route.sessionKey, AccountId: route.accountId, ChatType: "direct" as const, SenderName: ctx.userId, SenderId: ctx.userId, Provider: "wecom" as const, Surface: "wecom" as const, MessageSid: ctx.msgId, Timestamp: ctx.createTime * 1000, WasMentioned: false, CommandAuthorized: true, OriginatingChannel: "wecom" as const, OriginatingTo: wecomTo, }); ``` ### Technical Analysis The plugin advertises three direct-message policies: `open`, `pairing`, and `allowlist`. However, the inbound authorization logic only implements the `allowlist` branch. When `dmPolicy` is set to `pairing`, an unknown sender falls through to normal agent dispatch without any pairing request, approval lookup, or rejection. This behavior contradicts the documented guarantee that unknown users in pairing mode require a pairing code and administrator approval. The problem is compounded by setting `CommandAuthorized: true` for every message that reaches dispatch. This value is not derived from the configured policy or a verified pairing state. Consequently, an unpaired sender is represented to the OpenClaw runtime as authorized to issue commands. Cryptographic callback verification does not mitigate this a ...[truncated 1740 chars]- Remediation
View remediation
