fix: gate reset auth and infer whatsapp sender
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
- Docs: clarify Slack manifest scopes (current vs optional) with references. Thanks @jarvis-medmatic for PR #235.
|
||||
- Control UI: avoid Slack config ReferenceError by reading slack config snapshots. Thanks @sreekaransrinath for PR #249.
|
||||
- Telegram: honor routing.groupChat.mentionPatterns for group mention gating. Thanks @regenrek for PR #242.
|
||||
- Auto-reply: block unauthorized `/reset` and infer WhatsApp senders from E.164 inputs.
|
||||
|
||||
### Maintenance
|
||||
- Deps: bump pi-* stack, Slack SDK, discord-api-types, file-type, zod, and Biome.
|
||||
|
||||
@@ -18,16 +18,23 @@ export function resolveCommandAuthorization(params: {
|
||||
}): CommandAuthorization {
|
||||
const { ctx, cfg, commandAuthorized } = params;
|
||||
const surface = (ctx.Surface ?? "").trim().toLowerCase();
|
||||
const isWhatsAppSurface =
|
||||
surface === "whatsapp" ||
|
||||
const from = (ctx.From ?? "").replace(/^whatsapp:/, "");
|
||||
const to = (ctx.To ?? "").replace(/^whatsapp:/, "");
|
||||
const hasWhatsappPrefix =
|
||||
(ctx.From ?? "").startsWith("whatsapp:") ||
|
||||
(ctx.To ?? "").startsWith("whatsapp:");
|
||||
const looksLikeE164 = (value: string) =>
|
||||
Boolean(value && /^\+?\d{3,}$/.test(value.replace(/[^\d+]/g, "")));
|
||||
const inferWhatsApp =
|
||||
!surface &&
|
||||
Boolean(cfg.whatsapp?.allowFrom?.length) &&
|
||||
(looksLikeE164(from) || looksLikeE164(to));
|
||||
const isWhatsAppSurface =
|
||||
surface === "whatsapp" || hasWhatsappPrefix || inferWhatsApp;
|
||||
|
||||
const configuredAllowFrom = isWhatsAppSurface
|
||||
? cfg.whatsapp?.allowFrom
|
||||
: undefined;
|
||||
const from = (ctx.From ?? "").replace(/^whatsapp:/, "");
|
||||
const to = (ctx.To ?? "").replace(/^whatsapp:/, "");
|
||||
const allowFromList =
|
||||
configuredAllowFrom?.filter((entry) => entry?.trim()) ?? [];
|
||||
const allowAll =
|
||||
@@ -35,7 +42,9 @@ export function resolveCommandAuthorization(params: {
|
||||
allowFromList.length === 0 ||
|
||||
allowFromList.some((entry) => entry.trim() === "*");
|
||||
|
||||
const senderE164 = normalizeE164(ctx.SenderE164 ?? "");
|
||||
const senderE164 = normalizeE164(
|
||||
ctx.SenderE164 ?? (isWhatsAppSurface ? from : ""),
|
||||
);
|
||||
const ownerCandidates =
|
||||
isWhatsAppSurface && !allowAll
|
||||
? allowFromList.filter((entry) => entry !== "*")
|
||||
|
||||
@@ -173,6 +173,7 @@ export async function handleCommands(params: {
|
||||
shouldContinue: boolean;
|
||||
}> {
|
||||
const {
|
||||
ctx,
|
||||
cfg,
|
||||
command,
|
||||
directives,
|
||||
@@ -193,6 +194,18 @@ export async function handleCommands(params: {
|
||||
isGroup,
|
||||
} = params;
|
||||
|
||||
const resetRequested =
|
||||
command.commandBodyNormalized === "/reset" ||
|
||||
command.commandBodyNormalized === "reset" ||
|
||||
command.commandBodyNormalized === "/new" ||
|
||||
command.commandBodyNormalized === "new";
|
||||
if (resetRequested && !command.isAuthorizedSender) {
|
||||
logVerbose(
|
||||
`Ignoring /reset from unauthorized sender: ${command.senderE164 || "<unknown>"}`,
|
||||
);
|
||||
return { shouldContinue: false };
|
||||
}
|
||||
|
||||
const activationCommand = parseActivationCommand(
|
||||
command.commandBodyNormalized,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user