Research Paper

Dual-Context Scanning: Closing the Indirect Injection Gap in RAG Pipelines

TL;DR

Production RAG guardrails scan only the user query, leaving retrieved documents — the actual injection vector — unexamined. When defenders try to fix this by concatenating query + retrieved content into a single string, the injection signal gets diluted by surrounding benign text, and detection collapses.

We introduce dual-context scanning: scan the user query and retrieved documents as independent inputs, flag the request if either triggers detection. On a 5,000-case benchmark, this recovers 73.3% of otherwise-undetected indirect injections for ML-based guardrails and 41.5% for regex scanners, at false-positive rates of 5.7% and 6.6%.

The framework, benchmark, and reproducible eval suite are released as open source at github.com/tideon/ragshield.

The hidden gap in RAG security

Production RAG pipelines look like this: a user query goes in, retrieves chunks from a vector database, gets concatenated with the retrieved context, and is passed to the LLM for inference.

The security model most teams ship looks like this: a guardrail scans the user query for prompt-injection patterns before retrieval runs. If it passes, the request proceeds.

The problem: the retrieved documents never get scanned.They flow directly into the LLM context. And that's exactly where indirect prompt injection lives — adversarial instructions hidden in documents the attacker poisoned upstream (a shared knowledge base, a public web page, an email an employee uploaded).

The user's query is benign. The attack arrives through the retrieval channel.

┌──────────────────┐   ┌──────────────────┐   ┌──────────────────┐
│   User Query     │──▶│ Vector Database  │──▶│       LLM        │
│  "Summarize"     │   │    Retrieval     │   │    Response      │
└──────────────────┘   └──────────────────┘   └──────────────────┘
        ▲                       ▲
        │                       │
   Guardrail scans          No scan here
   only this surface        ── injection enters via retrieved doc
Figure 1 — The unscanned attack surface in standard RAG

Why naive defenses fail

The obvious fix is to concatenate the query and retrieved documents and run the guardrail on the combined string. Many production systems do exactly this.

It doesn't work.

When you concatenate a 50-token injection with 3,000 tokens of benign retrieved context, ML-based classifiers experience signal dilution— the malicious tokens get averaged into a sea of clean ones, and the classifier's confidence drops below threshold. The injection sails through.

We measured this empirically: a naive combined-string scan on LLM Guard catches only 46.4% of indirect injections that the same scanner would catch if presented with the malicious document alone.

Dual-context scanning

The fix is architectural, not algorithmic. Instead of feeding the scanner one big concatenated string, run two passes:

  1. Pass 1: scan the user query in isolation
  2. Pass 2: scan each retrieved chunk in isolation
  3. Decision: if either pass flags injection, block the request

Each pass preserves the signal-to-noise ratio of its input. The injection in a poisoned document is no longer drowned out by surrounding context — it's evaluated on its own terms.

# Conceptually:
def dual_context_scan(user_query, retrieved_docs):
    if guardrail.scan(user_query).is_injection:
        return BLOCK
    for doc in retrieved_docs:
        if guardrail.scan(doc).is_injection:
            return BLOCK
    return ALLOW

Results

We evaluated dual-context scanning against three baselines on RAG-INJECTION-5K, a 5,000-case benchmark spanning five injection categories and two benign classes:

ConfigurationScannerRecovery rateFalse-positive rate
User-only baselineLLM Guard0%
Naive combined stringLLM Guard46.4%
Dual-context (ours)LLM Guard73.3% (±1.9%)5.7%
Dual-context (ours)Regex baseline41.5% (±2.1%)6.6%

For the ML-based guardrail, dual-context scanning recovers a +73.3 percentage-point gain over the user-only baseline, and a +26.9 point gain over naive combined-string scanning. The false-positive rate stays manageable at 5.7%.

The regex scanner — much weaker as a starting baseline — still recovers a meaningful 41.5% of injections it would otherwise miss.

What this means for production

If you're running RAG in production today and your guardrail scans only the user query, your indirect-injection coverage is approximately zero. The attack surface is sitting inside your retrieval pipeline, and your defenses are looking elsewhere.

Dual-context scanning is a pipeline-sidedefense — it doesn't require retraining your LLM, modifying your prompts, or replacing your retriever. It sits in front of the LLM call, scans each context source independently, and short-circuits when injection is detected.

It's also complementary to model-side defenses (instruction hierarchy, StruQ, SecAlign). Use both. Training-side defenses reduce LLM susceptibility; pipeline-side defenses intercept injections before they reach the model.

Limitations

Dual-context scanning catches injections that anyguardrail can detect when presented with the malicious content alone. It does not magically detect injections that bypass the underlying scanner — if LLM Guard can't recognize a particular injection style, neither will dual-context scanning. The contribution is closing the deployment gap, not improving the underlying classifier.

Latency: scanning N retrieved chunks adds N additional guardrail calls. For most production setups (top-k retrieval where k ≤ 10) this is acceptable. For high-throughput or low-latency systems, batched scanning or early-exit strategies are worth exploring.

Open Source

RAG Shield: the framework, benchmark, and reproducible eval suite.

All code, the RAG-INJECTION-5K dataset, evaluation scripts, and result artifacts are released. Reproduce our numbers or extend the benchmark.

Cite this work
@misc{rallabandi2026dualcontext, title = {Dual-Context Scanning: Closing the Indirect Injection Gap in Retrieval-Augmented Generation Pipelines}, author = {Rallabandi, Saikiran}, year = {2026}, note = {Tideon Research} }

Need this shipped in your stack?

Tideon engineers AI systems with security gates baked into the lifecycle. Production-ready, fixed-scope.

Book a call