mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 09:01:22 +00:00
fix(auto-reply): prevent sender spoofing in group prompts
This commit is contained in:
@@ -12,7 +12,6 @@ import {
|
||||
resetInboundDedupe,
|
||||
shouldSkipDuplicateInbound,
|
||||
} from "./reply/inbound-dedupe.js";
|
||||
import { formatInboundBodyWithSenderMeta } from "./reply/inbound-sender-meta.js";
|
||||
import { normalizeInboundTextNewlines } from "./reply/inbound-text.js";
|
||||
import {
|
||||
buildMentionRegexes,
|
||||
@@ -80,7 +79,8 @@ describe("finalizeInboundContext", () => {
|
||||
const out = finalizeInboundContext(ctx);
|
||||
expect(out.Body).toBe("a\nb\nc");
|
||||
expect(out.RawBody).toBe("raw\nline");
|
||||
expect(out.BodyForAgent).toBe("a\nb\nc");
|
||||
// Prefer clean text over legacy envelope-shaped Body when RawBody is present.
|
||||
expect(out.BodyForAgent).toBe("raw\nline");
|
||||
expect(out.BodyForCommands).toBe("raw\nline");
|
||||
expect(out.CommandAuthorized).toBe(false);
|
||||
expect(out.ChatType).toBe("channel");
|
||||
@@ -101,58 +101,6 @@ describe("finalizeInboundContext", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatInboundBodyWithSenderMeta", () => {
|
||||
it("does nothing for direct messages", () => {
|
||||
const ctx: MsgContext = { ChatType: "direct", SenderName: "Alice", SenderId: "A1" };
|
||||
expect(formatInboundBodyWithSenderMeta({ ctx, body: "[X] hi" })).toBe("[X] hi");
|
||||
});
|
||||
|
||||
it("appends a sender meta line for non-direct messages", () => {
|
||||
const ctx: MsgContext = { ChatType: "group", SenderName: "Alice", SenderId: "A1" };
|
||||
expect(formatInboundBodyWithSenderMeta({ ctx, body: "[X] hi" })).toBe(
|
||||
"[X] hi\n[from: Alice (A1)]",
|
||||
);
|
||||
});
|
||||
|
||||
it("prefers SenderE164 in the label when present", () => {
|
||||
const ctx: MsgContext = {
|
||||
ChatType: "group",
|
||||
SenderName: "Bob",
|
||||
SenderId: "bob@s.whatsapp.net",
|
||||
SenderE164: "+222",
|
||||
};
|
||||
expect(formatInboundBodyWithSenderMeta({ ctx, body: "[X] hi" })).toBe(
|
||||
"[X] hi\n[from: Bob (+222)]",
|
||||
);
|
||||
});
|
||||
|
||||
it("appends with a real newline even if the body contains literal \\n", () => {
|
||||
const ctx: MsgContext = { ChatType: "group", SenderName: "Bob", SenderId: "+222" };
|
||||
expect(formatInboundBodyWithSenderMeta({ ctx, body: "[X] one\\n[X] two" })).toBe(
|
||||
"[X] one\\n[X] two\n[from: Bob (+222)]",
|
||||
);
|
||||
});
|
||||
|
||||
it("does not duplicate a sender meta line when one is already present", () => {
|
||||
const ctx: MsgContext = { ChatType: "group", SenderName: "Alice", SenderId: "A1" };
|
||||
expect(formatInboundBodyWithSenderMeta({ ctx, body: "[X] hi\n[from: Alice (A1)]" })).toBe(
|
||||
"[X] hi\n[from: Alice (A1)]",
|
||||
);
|
||||
});
|
||||
|
||||
it("does not append when the body already includes a sender prefix", () => {
|
||||
const ctx: MsgContext = { ChatType: "group", SenderName: "Alice", SenderId: "A1" };
|
||||
expect(formatInboundBodyWithSenderMeta({ ctx, body: "Alice (A1): hi" })).toBe("Alice (A1): hi");
|
||||
});
|
||||
|
||||
it("does not append when the sender prefix follows an envelope header", () => {
|
||||
const ctx: MsgContext = { ChatType: "group", SenderName: "Alice", SenderId: "A1" };
|
||||
expect(formatInboundBodyWithSenderMeta({ ctx, body: "[Signal Group] Alice (A1): hi" })).toBe(
|
||||
"[Signal Group] Alice (A1): hi",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("inbound dedupe", () => {
|
||||
it("builds a stable key when MessageSid is present", () => {
|
||||
const ctx: MsgContext = {
|
||||
@@ -256,8 +204,8 @@ describe("createInboundDebouncer", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("initSessionState sender meta", () => {
|
||||
it("injects sender meta into BodyStripped for group chats", async () => {
|
||||
describe("initSessionState BodyStripped", () => {
|
||||
it("prefers BodyForAgent over Body for group chats", async () => {
|
||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-sender-meta-"));
|
||||
const storePath = path.join(root, "sessions.json");
|
||||
const cfg = { session: { store: storePath } } as OpenClawConfig;
|
||||
@@ -265,6 +213,7 @@ describe("initSessionState sender meta", () => {
|
||||
const result = await initSessionState({
|
||||
ctx: {
|
||||
Body: "[WhatsApp 123@g.us] ping",
|
||||
BodyForAgent: "ping",
|
||||
ChatType: "group",
|
||||
SenderName: "Bob",
|
||||
SenderE164: "+222",
|
||||
@@ -275,10 +224,10 @@ describe("initSessionState sender meta", () => {
|
||||
commandAuthorized: true,
|
||||
});
|
||||
|
||||
expect(result.sessionCtx.BodyStripped).toBe("[WhatsApp 123@g.us] ping\n[from: Bob (+222)]");
|
||||
expect(result.sessionCtx.BodyStripped).toBe("ping");
|
||||
});
|
||||
|
||||
it("does not inject sender meta for direct chats", async () => {
|
||||
it("prefers BodyForAgent over Body for direct chats", async () => {
|
||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-sender-meta-direct-"));
|
||||
const storePath = path.join(root, "sessions.json");
|
||||
const cfg = { session: { store: storePath } } as OpenClawConfig;
|
||||
@@ -286,6 +235,7 @@ describe("initSessionState sender meta", () => {
|
||||
const result = await initSessionState({
|
||||
ctx: {
|
||||
Body: "[WhatsApp +1] ping",
|
||||
BodyForAgent: "ping",
|
||||
ChatType: "direct",
|
||||
SenderName: "Bob",
|
||||
SenderE164: "+222",
|
||||
@@ -295,7 +245,7 @@ describe("initSessionState sender meta", () => {
|
||||
commandAuthorized: true,
|
||||
});
|
||||
|
||||
expect(result.sessionCtx.BodyStripped).toBe("[WhatsApp +1] ping");
|
||||
expect(result.sessionCtx.BodyStripped).toBe("ping");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user