From 48e5cf7fe41cad51922cba3259cb3990acc8becd Mon Sep 17 00:00:00 2001 From: Ravi Tharuma <25951435+RaviTharuma@users.noreply.github.com> Date: Mon, 17 Aug 2026 12:04:48 +0200 Subject: [PATCH] fix(sse): do not ZWJ-obfuscate the substring hermes in user text (#10488) Keep the #8350 Hermes system-prompt drops, but remove hermes from the factory obfuscate_words list so hostnames and CLI mentions stay intact. Co-authored-by: Ravi Tharuma --- .../fixes/10484-hermes-obfuscate-zwj.md | 1 + open-sse/services/systemTransforms.ts | 7 +++-- .../settings/components/RoutingTab.tsx | 2 -- .../unit/8350-hermes-oauth-usage-400.test.ts | 31 +++++++++++++++++++ tests/unit/system-transforms.test.ts | 2 -- 5 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 changelog.d/fixes/10484-hermes-obfuscate-zwj.md diff --git a/changelog.d/fixes/10484-hermes-obfuscate-zwj.md b/changelog.d/fixes/10484-hermes-obfuscate-zwj.md new file mode 100644 index 0000000000..5e1dc60de1 --- /dev/null +++ b/changelog.d/fixes/10484-hermes-obfuscate-zwj.md @@ -0,0 +1 @@ +- fix(sse): stop ZWJ-obfuscating the substring "hermes" in user messages and hostnames (#10484) diff --git a/open-sse/services/systemTransforms.ts b/open-sse/services/systemTransforms.ts index e7542619e3..2bed25d741 100644 --- a/open-sse/services/systemTransforms.ts +++ b/open-sse/services/systemTransforms.ts @@ -96,9 +96,10 @@ export const DEFAULT_OBFUSCATE_WORDS = [ // Open WebUI additions "openwebui", "open-webui", - // Hermes additions (#8350) - "hermes-agent", - "hermes", + // Do not add "hermes" / "hermes-agent" here. #8350 is handled by + // HERMES_PARAGRAPH_ANCHORS + HERMES_IDENTITY_PREFIXES (system-prompt + // drops only). ZWJ on the short substring "hermes" rewrites user + // messages and hostnames (#10484). ]; /** diff --git a/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx b/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx index 22462ce866..5c844f80cb 100644 --- a/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx @@ -81,8 +81,6 @@ const DEFAULT_OBFUSCATE_WORDS = [ "codecompanion", "openwebui", "open-webui", - "hermes-agent", - "hermes", ]; // Mirror of DEFAULT_SYSTEM_TRANSFORMS_CONFIG from open-sse/services/systemTransforms.ts. diff --git a/tests/unit/8350-hermes-oauth-usage-400.test.ts b/tests/unit/8350-hermes-oauth-usage-400.test.ts index fd502183c4..51288c23be 100644 --- a/tests/unit/8350-hermes-oauth-usage-400.test.ts +++ b/tests/unit/8350-hermes-oauth-usage-400.test.ts @@ -68,3 +68,34 @@ test("non-Hermes system prompt passes through byte-identical through the claude "a normal operator system prompt with no third-party-agent anchors must pass through untouched" ); }); + +// #10484 — #8358 added "hermes" to DEFAULT_OBFUSCATE_WORDS. The ZWJ op +// targets user messages with a case-insensitive, no-word-boundary regex, so +// hostnames and ordinary mentions of the OmniRoute hermes CLI tool were +// rewritten. System-prompt identity drops (#8350) must stay; user text must not +// be mutated. +test("user message containing hermes hostname stays byte-identical (#10484)", () => { + const body = { + system: [ + { + type: "text", + text: "You are a helpful operator-configured assistant. Follow company policy X and always answer in English.", + }, + ], + messages: [ + { + role: "user", + content: "1. hermes\n2. hermes.example.ts.net\n3. Hermes on agent-001\n4. hermeS", + }, + ], + }; + const before = JSON.stringify(body); + applySystemTransformPipeline(PROVIDER_CLAUDE, body, DEFAULT_SYSTEM_TRANSFORMS_CONFIG); + assert.equal( + JSON.stringify(body), + before, + "user text containing the substring hermes must not receive ZWJ obfuscation" + ); + const content = (body.messages[0] as { content: string }).content; + assert.equal(content.includes("\u200d"), false, "no zero-width joiner in user text"); +}); diff --git a/tests/unit/system-transforms.test.ts b/tests/unit/system-transforms.test.ts index cf1f7391e0..047063d663 100644 --- a/tests/unit/system-transforms.test.ts +++ b/tests/unit/system-transforms.test.ts @@ -502,8 +502,6 @@ const UI_DEFAULTS_SNAPSHOT = { "codecompanion", "openwebui", "open-webui", - "hermes-agent", - "hermes", ], targets: ["system", "messages", "tools"], },