T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/validate.js:96- Finding
Unrestricted Enumeration of Cached WhatsApp Phone Numbers and JIDs
- Content
View full analysis
Vulnerability Details
File Location:
scripts/validate.js, lines 6–10, 18–43, and 96–101
Vulnerability Type: Unrestricted access to sensitive local WhatsApp cache data
Risk Level: MediumThe skill reads phone numbers from the OpenClaw WhatsApp/Baileys credential-cache directory. Its
listcommand prints cached phone numbers and corresponding WhatsApp JIDs without authorization checks, user confirmation, output masking, or an enforced maximum result count.Vulnerable Code
js const CREDS_PATH = path.join( process.env.OPENCLAW_STATE_DIR || path.join(os.homedir(), '.openclaw'), 'credentials', 'whatsapp', 'default' );js function loadKnownNumbers() { const numbers = new Set(); try { const files = fs.readdirSync(CREDS_PATH); for (const file of files) { // session-NUMBER.json if (file.startsWith('session-')) { const match = file.match(/session-(\d+)_/); if (match) numbers.add(match[1]); } // device-list-NUMBER.json if (file.startsWith('device-list-')) { const match = file.match(/device-list-(\d+)\.json/); if (match) numbers.add(match[1]); } } // Also load from contacts file try { const contactsPath = path.join(CREDS_PATH, 'contacts.json'); if (fs.existsSync(contactsPath)) { const contacts = JSON.parse(fs.readFileSync(contactsPath, 'utf8')); for (const jid of Object.keys(contacts)) { if (jid.endsWith('@s.whatsapp.net')) { numbers.add(jid.replace('@s.whatsapp.net', '')); } } } } catch (e) { /* contacts not available */ } } catch (error) { console.error(JSON.stringify({ error: error.message })); process.exit(1); } return numbers; }js function listKnown(limit = 50) { const numbers = Array.from(loadKnownNumbers()).slice(0, parseInt(limit)); ...[truncated 2610 chars]- Remediation
View remediation
Remediation Suggestions
- Remove the bulk
listcommand unless full contact enumeration is an explicit and necessary feature. - Require an explicit authorization check before accessing or displaying cached WhatsApp identifiers.
- Restrict the skill to single-number membership checks where possible, returning only a Boolean result rather than a phone number or JID.
- Mask sensitive values by default, such as displaying only the final two to four digits.
- Do not print reconstructed JIDs unless they are strictly required by an authorized workflow.
- Enforce a small, fixed upper bound on list results and reject non-integer, negative, non-finite, or excessive limits.
- Prevent sensitive output from being retained in agent transcripts and execution logs, or mark it for mandatory redaction.
- Apply least-privilege filesystem permissions to the WhatsApp credential-cache directory and execute the skill only in trusted contexts.
- Document that cache output contains personal data and establish appropriate retention, consent, and access-control policies.
- Remove the bulk
