Skip to content

fix(rag): close prompt-neutralizer bypass for cross-document titles#406

Merged
BigSimmo merged 1 commit into
mainfrom
claude/g-prompt-neutralizer-cross-document
Jul 8, 2026
Merged

fix(rag): close prompt-neutralizer bypass for cross-document titles#406
BigSimmo merged 1 commit into
mainfrom
claude/g-prompt-neutralizer-cross-document

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Summary

docs/rag-injection-threat-model.md (Vectors B/C) established that a document
title/file_name is a viable injection channel and must never reach the model
raw — buildRagSourceBlock already neutralizes per-result titles for that
reason. This PR closes three places that built prompt text directly from
document titles without going through that same neutralizeIdentityField
primitive:

  • buildCrossDocumentSourceGuide (src/lib/cross-document-synthesis.ts) —
    the per-document title in the "Cross-document synthesis guide:" block that
    feeds into the answer-generation prompt whenever cross-document synthesis
    is enabled.
  • buildCrossDocumentFusionBrief (same file) — the per-document title in the
    "Fast fused source brief:" block.
  • summarizeDocument (src/lib/rag.ts) — document.title interpolated raw
    into the Document: header of the single-document summary prompt, the
    highest-trust position in that prompt.

Why this wasn't already covered

tests/rag-injection.test.ts already covers neutralizeIdentityField and
buildRagSourceBlock's per-result title neutralization thoroughly, but these
three call sites build their own prompt strings from document titles
outside of buildRagSourceBlock, so they weren't exercised by that suite.

Testing

  • Added two regression tests to tests/cross-document-synthesis.test.ts
    proving a canonical injection idiom carried in a document title no longer
    survives into the generated guide/brief text (same idiom pattern used in
    tests/rag-injection.test.ts).
  • npx tsc --noEmit clean, npx eslint clean on all three changed files,
    npx vitest run tests/cross-document-synthesis.test.ts tests/rag-injection.test.ts
    — 17/17 passing.
  • No schema.sql / migration changes — no drift-manifest dependency, unlike
    the sibling R17/R5 PRs from this session.

🤖 Generated with Claude Code

docs/rag-injection-threat-model.md (Vectors B/C) flagged that a document
title/file_name is a viable injection channel and must never reach the model
raw. buildRagSourceBlock's per-result titles are already neutralized, but two
cross-document synthesis helpers built their own prompt text directly from
document titles without going through neutralizeIdentityField:

- buildCrossDocumentSourceGuide (src/lib/cross-document-synthesis.ts) — the
  per-document title in the "Cross-document synthesis guide:" block.
- buildCrossDocumentFusionBrief (same file) — the per-document title in the
  "Fast fused source brief:" block.
- summarizeDocument (src/lib/rag.ts) — document.title interpolated raw into
  the "Document:" header of the single-document summary prompt, the highest-
  trust position in that prompt.

All three now route through the same neutralizeIdentityField primitive
already covered by tests/rag-injection.test.ts. New regression tests added to
tests/cross-document-synthesis.test.ts proving an injection idiom carried in
a title no longer survives into the generated guide/brief text.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@supabase

supabase Bot commented Jul 8, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@BigSimmo
BigSimmo merged commit ca919f6 into main Jul 8, 2026
6 checks passed
@BigSimmo
BigSimmo deleted the claude/g-prompt-neutralizer-cross-document branch July 8, 2026 16:13
BigSimmo added a commit that referenced this pull request Jul 8, 2026
Resolve branch conflicts with main (post-#405/#406). Drift manifest will
be regenerated via CI because local Docker Desktop/WSL is unavailable.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant