From f236e0de9a02503efac9a69cb1efccf47617d135 Mon Sep 17 00:00:00 2001 From: LHMQ878 <72402929@cityu-dg.edu.cn> Date: Sat, 8 Aug 2026 17:00:39 +0800 Subject: [PATCH 1/2] fix: strip injected message-id suffix before paired tag regex Remove the legitimately injected suffix before running DCP_PAIRED_TAG_REGEX so in-text tag mentions cannot pair with it and truncate message content. Fixes #556 --- lib/messages/utils.ts | 4 +++- tests/message-priority.test.ts | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/messages/utils.ts b/lib/messages/utils.ts index eae03327..2941fbb7 100644 --- a/lib/messages/utils.ts +++ b/lib/messages/utils.ts @@ -7,6 +7,7 @@ const SUMMARY_ID_HASH_LENGTH = 16 const DCP_BLOCK_ID_TAG_REGEX = /(])[^>]*>)b\d+(<\/dcp-message-id>)/g const DCP_PAIRED_TAG_REGEX = /]*>[\s\S]*?<\/dcp[^>]*>/gi const DCP_UNPAIRED_TAG_REGEX = /<\/?dcp[^>]*>/gi +const INJECTED_MESSAGE_ID_SUFFIX_REGEX = /\nm\d+<\/dcp-message-id>\s*$/ const generateStableId = (prefix: string, seed: string): string => { const hash = createHash("sha256").update(seed).digest("hex").slice(0, SUMMARY_ID_HASH_LENGTH) @@ -163,7 +164,8 @@ export const replaceBlockIdsWithBlocked = (text: string): string => { } export const stripHallucinationsFromString = (text: string): string => { - return text.replace(DCP_PAIRED_TAG_REGEX, "").replace(DCP_UNPAIRED_TAG_REGEX, "") + const withoutInjectedSuffix = text.replace(INJECTED_MESSAGE_ID_SUFFIX_REGEX, "") + return withoutInjectedSuffix.replace(DCP_PAIRED_TAG_REGEX, "").replace(DCP_UNPAIRED_TAG_REGEX, "") } export const stripHallucinations = (messages: WithParts[]): void => { diff --git a/tests/message-priority.test.ts b/tests/message-priority.test.ts index 1342ca1b..401c023d 100644 --- a/tests/message-priority.test.ts +++ b/tests/message-priority.test.ts @@ -814,6 +814,18 @@ test("hallucination stripping does not affect non-dcp tags", async () => { ) }) +test("hallucination stripping preserves content when dcp-message-id is mentioned in text (issue #556)", () => { + const input = + "The tag called `` is used to track messages. " + + "This text should survive.\n\n" + + "m0369" + + assert.equal( + stripHallucinationsFromString(input), + "The tag called `` is used to track messages. This text should survive.\n", + ) +}) + test("injectMessageIds skips empty assistant messages to avoid prefill (issue #463)", () => { const sessionID = "ses_empty_assistant" const messages: WithParts[] = [ From 25417d2befe557954992fc2569af94b0b23c9c97 Mon Sep 17 00:00:00 2001 From: Daniel Smolsky Date: Sat, 15 Aug 2026 22:58:06 -0400 Subject: [PATCH 2/2] fix: update vulnerable brace expansion --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2983b1ca..d90568eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1641,9 +1641,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0"