refactor(security): make empty allowlist behavior explicit

This commit is contained in:
Peter Steinberger
2026-02-21 19:54:52 +01:00
parent ed960ba4eb
commit 2ba6de7eaa
3 changed files with 35 additions and 1 deletions

View File

@@ -1,5 +1,6 @@
import { describe, expect, it } from "vitest";
import {
isAllowedBlueBubblesSender,
looksLikeBlueBubblesTargetId,
normalizeBlueBubblesMessagingTarget,
parseBlueBubblesTarget,
@@ -181,3 +182,21 @@ describe("parseBlueBubblesAllowTarget", () => {
});
});
});
describe("isAllowedBlueBubblesSender", () => {
it("denies when allowFrom is empty", () => {
const allowed = isAllowedBlueBubblesSender({
allowFrom: [],
sender: "+15551234567",
});
expect(allowed).toBe(false);
});
it("allows wildcard entries", () => {
const allowed = isAllowedBlueBubblesSender({
allowFrom: ["*"],
sender: "+15551234567",
});
expect(allowed).toBe(true);
});
});

View File

@@ -37,6 +37,18 @@ describe("isAllowedParsedChatSender", () => {
expect(allowed).toBe(false);
});
it("can explicitly allow when allowFrom is empty", () => {
const allowed = isAllowedParsedChatSender({
allowFrom: [],
sender: "+15551234567",
emptyAllowFrom: "allow",
normalizeSender: (sender) => sender,
parseAllowTarget,
});
expect(allowed).toBe(true);
});
it("allows wildcard entries", () => {
const allowed = isAllowedParsedChatSender({
allowFrom: ["*"],

View File

@@ -21,12 +21,15 @@ export function isAllowedParsedChatSender<TParsed extends ParsedChatAllowTarget>
chatId?: number | null;
chatGuid?: string | null;
chatIdentifier?: string | null;
emptyAllowFrom?: "deny" | "allow";
normalizeSender: (sender: string) => string;
parseAllowTarget: (entry: string) => TParsed;
}): boolean {
const allowFrom = params.allowFrom.map((entry) => String(entry).trim());
if (allowFrom.length === 0) {
return false;
// Fail closed by default. Callers can opt into legacy "empty = allow all"
// behavior explicitly when a surface intentionally treats an empty list as open.
return params.emptyAllowFrom === "allow";
}
if (allowFrom.includes("*")) {
return true;