diff --git a/src/auto-reply/reply/strip-inbound-meta.test.ts b/src/auto-reply/reply/strip-inbound-meta.test.ts index da1979d1874..240c16d528b 100644 --- a/src/auto-reply/reply/strip-inbound-meta.test.ts +++ b/src/auto-reply/reply/strip-inbound-meta.test.ts @@ -102,4 +102,20 @@ describe("stripInboundMetadata", () => { This is plain user text`; expect(stripInboundMetadata(input)).toBe(input); }); + + it("does not strip lookalike sentinel lines with extra text", () => { + const input = `Conversation info (untrusted metadata): please ignore +\`\`\`json +{"x": 1} +\`\`\` +Real user content`; + expect(stripInboundMetadata(input)).toBe(input); + }); + + it("does not strip sentinel text when json fence is missing", () => { + const input = `Sender (untrusted metadata): +name: test +Hello from user`; + expect(stripInboundMetadata(input)).toBe(input); + }); }); diff --git a/src/auto-reply/reply/strip-inbound-meta.ts b/src/auto-reply/reply/strip-inbound-meta.ts index 764722aeea0..06da35b4ca0 100644 --- a/src/auto-reply/reply/strip-inbound-meta.ts +++ b/src/auto-reply/reply/strip-inbound-meta.ts @@ -32,8 +32,13 @@ const SENTINEL_FAST_RE = new RegExp( .join("|"), ); +function isInboundMetaSentinelLine(line: string): boolean { + const trimmed = line.trim(); + return INBOUND_META_SENTINELS.some((sentinel) => sentinel === trimmed); +} + function shouldStripTrailingUntrustedContext(lines: string[], index: number): boolean { - if (!lines[index]?.startsWith(UNTRUSTED_CONTEXT_HEADER)) { + if (lines[index]?.trim() !== UNTRUSTED_CONTEXT_HEADER) { return false; } const probe = lines.slice(index + 1, Math.min(lines.length, index + 8)).join("\n"); @@ -89,7 +94,12 @@ export function stripInboundMetadata(text: string): string { } // Detect start of a metadata block. - if (!inMetaBlock && INBOUND_META_SENTINELS.some((s) => line.startsWith(s))) { + if (!inMetaBlock && isInboundMetaSentinelLine(line)) { + const next = lines[i + 1]; + if (next?.trim() !== "```json") { + result.push(line); + continue; + } inMetaBlock = true; inFencedJson = false; continue; @@ -136,14 +146,14 @@ export function stripLeadingInboundMetadata(text: string): string { return ""; } - if (!INBOUND_META_SENTINELS.some((s) => lines[index].startsWith(s))) { + if (!isInboundMetaSentinelLine(lines[index])) { const strippedNoLeading = stripTrailingUntrustedContextSuffix(lines); return strippedNoLeading.join("\n"); } while (index < lines.length) { const line = lines[index]; - if (!INBOUND_META_SENTINELS.some((s) => line.startsWith(s))) { + if (!isInboundMetaSentinelLine(line)) { break; }