T05 · Unauthorized Access and Privilege Escalation
- Location
bridge.mjs:288- Finding
Unauthenticated Nostr Senders Can Submit Prompts to the OpenClaw Agent
- Content
View full analysis
console.error("[bridge] queue error:", e.message)); } ``` The queued message is subsequently submitted to the agent without an authorization check: ```js async function getReply(plaintext, senderPub) { const prompt = `[safeTok DM from ${senderPub.slice(0, 16)}…]\n${plaintext}`; // ... const ack = await gwRequest("chat.send", { sessionKey: SESSION, message: prompt, deliver: false, idempotencyKey: randomUUID(), }); ``` The relay subscription accepts events for the bridge from every sender: ```js ws.send(JSON.stringify(["REQ", sub, { kinds: [4], "#p": [MY_PUB], since: SINCE }])); ``` ### Technical Analysis The bridge does not maintain or enforce an authorized-sender allowlist. Any sender able to construct a decryptable Nostr DM addressed to the bridge can cause its plaintext to be inserted directly into the dedicated OpenClaw session. The README recommends setting an OpenClaw `dmPolicy`, but this implementation communicates directly with the Gateway WebSocket through `chat.send`. No corresponding policy enforcement is present in the bridge code. Consequently, documentation alone does not establish an access-control boundary. Because message plaintext becomes an agent prompt, an unauthorized sender may provide adversarial instructions or prompt-injection content. The eventual effect depends on the tools and permissions assigned to the OpenClaw agent. ### Attack Path 1. An attacker obtains ...[truncated 990 chars]- Remediation
View remediation
key.trim().toLowerCase()) .filter(Boolean), ); function handleDm(ev) { if (!ALLOWED_SENDERS.has(ev.pubkey?.toLowerCase())) { console.warn("[bridge] rejected DM from unauthorized sender"); return; } // Continue only after event validation and authorization. } ``` ]]>
