fix(whatsapp): authorize first-contact LID senders
This commit is contained in:
@@ -63,6 +63,15 @@ export function expandWhatsAppIdentifiers(identifier, sessionDir) {
|
||||
return resolved;
|
||||
}
|
||||
|
||||
export function matchesAllowedSender(senderId, senderPn, allowedUsers, sessionDir) {
|
||||
// WhatsApp Multi-Device can expose a first-contact sender as an opaque LID
|
||||
// before it persists LID mapping files. Baileys supplies the same sender's
|
||||
// authenticated phone JID separately in msg.key.senderPn, so consult it
|
||||
// as an additional alias without changing the allowlist itself.
|
||||
return matchesAllowedUser(senderId, allowedUsers, sessionDir)
|
||||
|| matchesAllowedUser(senderPn, allowedUsers, sessionDir);
|
||||
}
|
||||
|
||||
export function matchesAllowedUser(senderId, allowedUsers, sessionDir) {
|
||||
// Empty allowlist = NO ONE allowed (secure default, #8389). Operators
|
||||
// who want an open bot must set ``WHATSAPP_ALLOWED_USERS=*`` explicitly.
|
||||
|
||||
@@ -6,6 +6,7 @@ import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
||||
|
||||
import {
|
||||
expandWhatsAppIdentifiers,
|
||||
matchesAllowedSender,
|
||||
matchesAllowedUser,
|
||||
normalizeWhatsAppIdentifier,
|
||||
parseAllowedUsers,
|
||||
@@ -46,6 +47,27 @@ test('matchesAllowedUser accepts mapped lid sender when allowlist only contains
|
||||
}
|
||||
});
|
||||
|
||||
test('matchesAllowedSender accepts Baileys senderPn when a first-contact LID has no mapping yet', () => {
|
||||
const sessionDir = mkdtempSync(path.join(os.tmpdir(), 'hermes-wa-allowlist-'));
|
||||
|
||||
try {
|
||||
const allowedUsers = parseAllowedUsers('+19175395595');
|
||||
// On a first message from a WhatsApp Multi-Device contact, Baileys can
|
||||
// emit a LID as senderId before it has written LID mapping files, while
|
||||
// senderPn carries WhatsApp's authenticated phone JID.
|
||||
assert.equal(
|
||||
matchesAllowedSender('267383306489914@lid', '19175395595@s.whatsapp.net', allowedUsers, sessionDir),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
matchesAllowedSender('267383306489914@lid', '18881234567@s.whatsapp.net', allowedUsers, sessionDir),
|
||||
false,
|
||||
);
|
||||
} finally {
|
||||
rmSync(sessionDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test('matchesAllowedUser treats * as allow-all wildcard', () => {
|
||||
const sessionDir = mkdtempSync(path.join(os.tmpdir(), 'hermes-wa-allowlist-'));
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import { randomBytes, createHash } from 'crypto';
|
||||
import { execFileSync } from 'child_process';
|
||||
import { tmpdir } from 'os';
|
||||
import qrcode from 'qrcode-terminal';
|
||||
import { matchesAllowedUser, parseAllowedUsers } from './allowlist.js';
|
||||
import { matchesAllowedSender, matchesAllowedUser, parseAllowedUsers } from './allowlist.js';
|
||||
import { createOutboundIdTracker } from './outbound_ids.js';
|
||||
import { classifyOwnerMessageGate } from './owner_message_gate.js';
|
||||
import {
|
||||
@@ -525,8 +525,10 @@ async function startSocket() {
|
||||
|
||||
const chatId = msg.key.remoteJid;
|
||||
const senderId = msg.key.participant || chatId;
|
||||
const senderPn = msg.key.senderPn || '';
|
||||
const resolvedSenderId = senderPn || senderId;
|
||||
const isGroup = chatId.endsWith('@g.us');
|
||||
const senderNumber = senderId.replace(/@.*/, '');
|
||||
const senderNumber = resolvedSenderId.replace(/@.*/, '');
|
||||
emitDebugEvent({
|
||||
stage: 'upsert',
|
||||
type,
|
||||
@@ -627,7 +629,7 @@ async function startSocket() {
|
||||
} catch {}
|
||||
continue;
|
||||
}
|
||||
if (WHATSAPP_DM_POLICY !== 'pairing' && !matchesAllowedUser(senderId, ALLOWED_USERS, SESSION_DIR)) {
|
||||
if (WHATSAPP_DM_POLICY !== 'pairing' && !matchesAllowedSender(senderId, senderPn, ALLOWED_USERS, SESSION_DIR)) {
|
||||
try {
|
||||
console.log(JSON.stringify({
|
||||
event: 'ignored',
|
||||
@@ -703,7 +705,7 @@ async function startSocket() {
|
||||
const event = await extractBridgeEvent({
|
||||
msg,
|
||||
chatId,
|
||||
senderId,
|
||||
senderId: resolvedSenderId,
|
||||
senderNumber,
|
||||
botIds,
|
||||
isGroup,
|
||||
|
||||
Reference in New Issue
Block a user