T09 · Insecure Skill Coding Practices
- Location
install.sh:221- Finding
Unrestricted WhatsApp Payload Forwarding Through Patched Reply Function
- Content
View full analysis
Vulnerability Details
File Location:
install.sh, lines 221-223
Vulnerability Type: Insufficient input and payload validation
Risk Level: MediumVulnerable Code
javascript const reply = async (textOrPayload) => { const payload = typeof textOrPayload === 'string' ? { text: textOrPayload } : textOrPayload; await sendTrackedMessage(chatJid, payload); };This JavaScript is embedded in the installer and inserted into OpenClaw's global
login-*.jsdistribution file.Technical Analysis
The original text-only
reply()interface is changed to accept either a string or an arbitrary object. When the argument is not a string, the object is passed unchanged tosendTrackedMessage().The function does not:
- Confirm that the supplied value is a non-null plain object.
- Restrict the object to the intended
textandmentionsproperties. - Validate mention identifiers.
- Reject unsupported Baileys message fields.
- Enforce payload size or content limits.
Consequently, this patch broadens a text-delivery interface into a generic Baileys message-payload forwarding interface. Its exploitability depends on whether an untrusted or compromised caller can control the argument passed to
reply(). The reviewed package does not itself demonstrate such external control, but the missing validation creates an unsafe trust boundary in the globally patched OpenClaw function.Attack Path
- The installer patches OpenClaw's global
login-*.jsfile. - A caller capable of controlling the argument to the patched
reply()function supplies an object rather than a string. - The function accepts the object without checking its properties.
- The complete object is forwarded to
sendTrackedMessage(chatJid, payload). - Baileys processes any supported message fields present in that object, potentially producing message behavior beyond the intended text-and-mentions feature.
This path requi ...[truncated 637 chars]
- Remediation
View remediation
Remediation Suggestions
Replace arbitrary object forwarding with explicit payload construction and validation:
javascript const reply = async (value) => { if (typeof value === "string") { await sendTrackedMessage(chatJid, { text: value }); return; } if ( value === null || typeof value !== "object" || Array.isArray(value) || typeof value.text !== "string" ) { throw new TypeError("Invalid reply payload"); } const mentions = Array.isArray(value.mentions) ? value.mentions.filter( (jid) => typeof jid === "string" && /^\d{10,20}@lid$/.test(jid) ) : []; await sendTrackedMessage(chatJid, { text: value.text, mentions, }); };Additional hardening should include:
- Rejecting every property except
textandmentions. - Applying reasonable limits to text length and mention count.
- Verifying that mention LIDs belong to the current group before sending.
- Keeping the mention-specific wrapper separate from the general message-sending API.
- Adding tests that prove media, interactive-message, quoted-message, and protocol fields cannot pass through this interface.
- Rejecting every property except
