Files
hermes-agent/scripts/whatsapp-bridge/allowlist.test.mjs
Teknium 84a541b619 feat: support * wildcard in platform allowlists and improve WhatsApp docs
* docs: clarify WhatsApp allowlist behavior and document WHATSAPP_ALLOW_ALL_USERS

- Add WHATSAPP_ALLOW_ALL_USERS and WHATSAPP_DEBUG to env vars reference
- Warn that * is not a wildcard and silently blocks all messages
- Show WHATSAPP_ALLOWED_USERS as optional, not required
- Update troubleshooting with the * trap and debug mode tip
- Fix Security section to mention the allow-all alternative

Prompted by a user report in Discord where WHATSAPP_ALLOWED_USERS=*
caused all incoming messages to be silently dropped at the bridge level.

* feat: support * wildcard in platform allowlists

Follow the precedent set by SIGNAL_GROUP_ALLOWED_USERS which already
supports * as an allow-all wildcard.

Bridge (allowlist.js): matchesAllowedUser() now checks for * in the
allowedUsers set before iterating sender aliases.

Gateway (run.py): _is_authorized() checks for * in allowed_ids after
parsing the allowlist. This is generic — works for all platforms, not
just WhatsApp.

Updated docs to document * as a supported value instead of warning
against it. Added WHATSAPP_ALLOW_ALL_USERS and WHATSAPP_DEBUG to
the env vars reference.

Tests: JS allowlist test + 2 Python gateway tests (WhatsApp + Telegram
to verify cross-platform behavior).
2026-03-31 10:42:03 -07:00

60 lines
2.5 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import os from 'node:os';
import path from 'node:path';
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
import {
expandWhatsAppIdentifiers,
matchesAllowedUser,
normalizeWhatsAppIdentifier,
parseAllowedUsers,
} from './allowlist.js';
test('normalizeWhatsAppIdentifier strips jid syntax and plus prefix', () => {
assert.equal(normalizeWhatsAppIdentifier('+19175395595@s.whatsapp.net'), '19175395595');
assert.equal(normalizeWhatsAppIdentifier('267383306489914@lid'), '267383306489914');
assert.equal(normalizeWhatsAppIdentifier('19175395595:12@s.whatsapp.net'), '19175395595');
});
test('expandWhatsAppIdentifiers resolves phone and lid aliases from session files', () => {
const sessionDir = mkdtempSync(path.join(os.tmpdir(), 'hermes-wa-allowlist-'));
try {
writeFileSync(path.join(sessionDir, 'lid-mapping-19175395595.json'), JSON.stringify('267383306489914'));
writeFileSync(path.join(sessionDir, 'lid-mapping-267383306489914_reverse.json'), JSON.stringify('19175395595'));
const aliases = expandWhatsAppIdentifiers('267383306489914@lid', sessionDir);
assert.deepEqual([...aliases].sort(), ['19175395595', '267383306489914']);
} finally {
rmSync(sessionDir, { recursive: true, force: true });
}
});
test('matchesAllowedUser accepts mapped lid sender when allowlist only contains phone number', () => {
const sessionDir = mkdtempSync(path.join(os.tmpdir(), 'hermes-wa-allowlist-'));
try {
writeFileSync(path.join(sessionDir, 'lid-mapping-19175395595.json'), JSON.stringify('267383306489914'));
writeFileSync(path.join(sessionDir, 'lid-mapping-267383306489914_reverse.json'), JSON.stringify('19175395595'));
const allowedUsers = parseAllowedUsers('+19175395595');
assert.equal(matchesAllowedUser('267383306489914@lid', allowedUsers, sessionDir), true);
assert.equal(matchesAllowedUser('188012763865257@lid', 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-'));
try {
const allowedUsers = parseAllowedUsers('*');
assert.equal(matchesAllowedUser('19175395595@s.whatsapp.net', allowedUsers, sessionDir), true);
assert.equal(matchesAllowedUser('267383306489914@lid', allowedUsers, sessionDir), true);
} finally {
rmSync(sessionDir, { recursive: true, force: true });
}
});