You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Found while sweeping #5857. That issue scoped the fix to chat-analyst-context.ts + brief-story-context.ts; the same weakness is present in three sibling prompt-context modules that were outside its scope.
Problem
Same root cause as #5850/#5857: sanitizeForPrompt (server/_shared/llm-sanitize.js:79) strips injection phrases but deliberately preserves a lone newline — it splits on \n, filters role-prefixed lines, rejoins, then collapses only runs of 2+ whitespace. Any block composed as `- ${x}` (or `Label: ${x}`) and joined with \n therefore lets one feed item forge an extra row the model reads as a separate, real datum.
sanitizeForPromptLine() now exists in server/_shared/llm-sanitize.js (added by the #5857 fix) — it is sanitizeForPrompt plus a full whitespace-run collapse. These sites should adopt it.
Affected sites (by inspection — not separately reproduced)
server/worldmonitor/intelligence/v1/brief-why-matters-prompt.ts:270-278 — Headline: / Description: / Source: / Severity: / Category: / Country: lines joined by \n. Fields come from sanitizeStoryFields(story); a newline in any of them forges an extra Key: value line the model reads as a real field.
Also worth checking scripts/lib/brief-llm.mjs:284-288 and :522-526 for the same shape.
Fix
sanitizeForPromptLine(...) at each line-composing call site; keep plain sanitizeForPrompt on prose bodies whose internal newlines are legitimate. For (3), that also closes the missing-sanitization gap.
Acceptance criteria
A failing test first, per affected module: one feed item containing \n must yield exactly the number of rows its payload declares.
P2, same threat model as #5857: exploiting it needs attacker-influenced text in a seeded feed, which is upstream- rather than user-controlled — but that is exactly what #3724's hard-sanitization policy at these prompt boundaries exists for, and the fix is a few characters per call site.
Found while sweeping #5857. That issue scoped the fix to
chat-analyst-context.ts+brief-story-context.ts; the same weakness is present in three sibling prompt-context modules that were outside its scope.Problem
Same root cause as #5850/#5857:
sanitizeForPrompt(server/_shared/llm-sanitize.js:79) strips injection phrases but deliberately preserves a lone newline — it splits on\n, filters role-prefixed lines, rejoins, then collapses only runs of 2+ whitespace. Any block composed as`- ${x}`(or`Label: ${x}`) and joined with\ntherefore lets one feed item forge an extra row the model reads as a separate, real datum.sanitizeForPromptLine()now exists inserver/_shared/llm-sanitize.js(added by the #5857 fix) — it issanitizeForPromptplus a full whitespace-run collapse. These sites should adopt it.Affected sites (by inspection — not separately reproduced)
server/worldmonitor/intelligence/v1/deduct-situation.ts:69-77—`- "${title}" — Yes ${pct}% (${vol} volume)`joined by\nunder a## Prediction Market Oddsheader.titlegoes throughsanitizeForPromptonly. Exact same shape asbuildPredictionMarkets, which fix(intel): newline in feed text forges extra bullets in analyst prompt blocks (sibling formatters missed by #5850) #5857 fixed.server/worldmonitor/intelligence/v1/brief-why-matters-prompt.ts:270-278—Headline:/Description:/Source:/Severity:/Category:/Country:lines joined by\n. Fields come fromsanitizeStoryFields(story); a newline in any of them forges an extraKey: valueline the model reads as a real field.server/worldmonitor/intelligence/v1/_country-brief-context.ts:210-213—headlineLinesare rawitem.titlevalues, not sanitized at all, joined by\nunder aHeadlines:marker. This one is worse than the fix(intel): newline in feed text forges extra bullets in analyst prompt blocks (sibling formatters missed by #5850) #5857 sites: it is missing both the delimiter guard and the LLM prompt injection: news headlines use structural-only sanitizer, bypassing semantic injection filters #3724 content sanitization.Also worth checking
scripts/lib/brief-llm.mjs:284-288and:522-526for the same shape.Fix
sanitizeForPromptLine(...)at each line-composing call site; keep plainsanitizeForPrompton prose bodies whose internal newlines are legitimate. For (3), that also closes the missing-sanitization gap.Acceptance criteria
\nmust yield exactly the number of rows its payload declares.sanitizeForPromptLineback tosanitizeForPromptmust turn each new test red (this is how the fix(intel): newline in feed text forges extra bullets in analyst prompt blocks (sibling formatters missed by #5850) #5857 guards were verified: 17 tests went red under that mutant).Severity
P2, same threat model as #5857: exploiting it needs attacker-influenced text in a seeded feed, which is upstream- rather than user-controlled — but that is exactly what #3724's hard-sanitization policy at these prompt boundaries exists for, and the fix is a few characters per call site.