Build1 distinct publisher3 min readUpdated
A developer's noise filter and reranker fixed a retrieval bug and exposed a worse one. If ordinary retrieved text can hijack a prompt, injection is a property of your corpus, not your threat model.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
A developer testing a small open-source retrieval pipeline reports that retrieved document text took over his prompt with nobody on the other end: in his own words, the pipeline hit "a real prompt injection, triggered entirely by accident, by a book about LLMs" [1]. That detail matters more than the fix, because it relocates prompt injection from the adversarial-input column to the retrieval-surface column, where it becomes a corpus problem you already own.
The setup is deliberately modest. The pipeline compares two ways of answering a question about a document: retrieve the most relevant snippets and feed only those to the model, or hand the model the whole document and ask directly [2]. Retrieval is BGE-M3, generation is Qwen3, all on a free Google Colab GPU [3].
The precedent from part 1 is the same mechanism without the instruction-following. Asked what a book about large language models was about, the RAG path confidently answered that it concerned "machine learning research communication via illustrated web articles" [4]. The cause was not the model: retrieval had grabbed a footnote buried in the book's dedication page [5]. The original patch only stripped bibliographies at the end of academic papers and never touched front matter, which is exactly where the failure lived [6].
The rewrite is two layers. A noise filter now runs on every chunk before it is embedded, flagging anything structurally shaped like a table of contents, an index, or a block of footnotes [7]. The signals are a digit ratio above 0.12, two or more ". . ." runs or three or more "..." runs, and four or more non-empty lines where more than 70 percent are shorter than 40 characters [8]. That digit threshold amounts to roughly one character in eight being a numeral [3]. The author is candid that these are cheap pattern matches on what junk looks like after a PDF becomes plain text [9]. Then retrieval pulls 20 candidates and a cross-encoder, bge-reranker-v2-m3, scores each question-chunk pair, keeping the top 5 [10], which discards 15 of every 20 candidates [2]. The stated purpose is to catch noise that slips past the filter [11].
Both layers judge relevance, not trust, and that is the gap. None of the three filter checks inspects meaning, so a chunk of well-formed prose that happens to contain instructions passes all of them [4]. The reranker scores how well a chunk answers the question, so an instruction-bearing chunk that is genuinely on-topic gets promoted rather than dropped [5]. A book about LLMs, queried about LLMs, is the worst case: the injecting text is also the most relevant text.
The regression test is a useful control. On the English-Nepali legal machine translation paper, both paths agreed on what the document was about [12], with RAG citing roughly 125,000 parallel sentences and the direct path reporting BLEU scores of 7.98 and 6.63 [13]. RAG even surfaced a confidentiality restriction the direct answer omitted [14]. The noise filter flagged 0 of that paper's 27 chunks [15], a 0 percent flag rate [1], which tells you the filter is quiet on clean prose and therefore no defence at all against clean prose that gives orders.
Two things to watch. The supplied text breaks off before the injection itself is walked through [16], so the actual trigger string and the model's response are still unpublished. And the direct-reading baseline is the natural control: if the same document steers the whole-document path too, this is a model problem; if only the retrieval path breaks, the fix belongs in ingestion, where chunks would need provenance and instruction screening, not just tidier formatting.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
The author reports finding "a real prompt injection, triggered entirely by accident, by a book about LLMs" while testing a fix to an earlier retrieval bug.
The author states the reranker gives any noisy chunk that slips past the noise filter a second chance to get caught and pushed out.
The pipeline compares two ways of answering questions about a document: RAG, which searches the document for the most relevant snippets and feeds only those to the model, and Direct, where the model reads the whole document (or as much as fits) and answers from that.
The stack is BGE-M3 for retrieval and Qwen3 for answer generation, running for free on a Google Colab GPU.
In part 1, asked what a book about large language models was about, the RAG answer said it was about "machine learning research communication via illustrated web articles", which the author calls nonsense.
The cause of the part 1 error was that retrieval had grabbed a footnote buried in the book's dedication page instead of content about the book's real subject.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Single self-reported experiment, shown in detail
Everything rests on one first-person dev.to post, but that post is unusually concrete for its class: the filter implementation is printed in full, the retrieval/rerank configuration is specified, model outputs are quoted verbatim, and the offending chunk and its rank are named. Against that, the sample is two documents and single runs, with no repository, no repeated trials, no quantified retrieval metrics and no independent corroboration, and the ledger's own note about where the text ends does not match the supplied body -- so the mechanism is well illustrated while its generality is unmeasured.
One hobby pipeline, no deployment evidence
Observed adoption is limited to the author's own free-tier Colab experiment using off-the-shelf open models. There is no production deployment, no user count, no organisational usage and no third party reproducing the filter or the incident. The security incident is real but self-inflicted inside a test harness, so it evidences the hazard rather than any uptake.
Demonstration solid, generalisation ahead of it
The narrow claim -- retrieved benign text can override the user's question -- is directly demonstrated and, if anything, understated in the post's own tone. The surrounding framing that injection is a property of the corpus rather than the threat model is a broader conclusion than one book chunk in one hobby pipeline can carry, and the post presents the noise filter and reranker as defences while its own incident shows neither stage inspects instructions. Mild overstatement, not inflation.
Self-published series post, no vendor stake disclosed
The post is an individual developer's numbered series entry on dev.to, which carries an ordinary audience-building and continuity incentive -- the narrative is structured around a cliffhanger discovery and forward references to later parts. Offsetting that, no product, employer, sponsor or paid service is promoted, the tooling described is free and open, and negative results about the author's own earlier fix are reported openly. No commercial conflict is visible in the supplied material.
Mechanism credible, magnitude uncertain
Confidence is moderate: the demonstrated mechanism is internally consistent, code-level and matches well-understood behaviour of instruction-following models over retrieved context, so the qualitative finding is likely robust. Uncertainty is concentrated in scope -- one publisher, one developer, two documents, no reproduction, no mitigation tested, and a ledger/body discrepancy about where the text ends -- so any quantitative or corpus-wide reading should be held loosely.
build
The fence was fine, the test was green, and the injection still worked1 distinct publisher
build
QUASAR says the 2-bit QAT loss floor is a weighting bug, not a law of physics1 distinct publisher
security
OWASP keeps prompt injection at number one and starts managing the blast radius1 distinct publisher
build
Your model cannot tell your instructions from the customer's, and that is the whole bug1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 20, 2026