Back to blog
RAG Systems

RAG Prompt Injection Through Documents: A Practical Security Boundary

Retrieved text can supply evidence, never application authority

Trust contracts, isolated document signals, action gates and reviewable routes

DOC-GUARD-7 is a public synthetic architecture example, not a security guarantee
RAG prompt injection, document security, untrusted retrieval, AI security review and grounded AI systems
Primary nodeDocument trust boundary
Routing modeDOC-GUARD-7
StatusPUBLISHED
Abstract document retrieval pipeline isolating an untrusted instruction signal behind a trust boundary before human review
DOC_GUARD_7_V01: a document may offer cited evidence, but it cannot rewrite application policy or trigger an action.
TERMINAL_PREVIEW.LOG
$ inspect-documents --contract DOC-GUARD-7
> bind: caller / collection / action boundary
> retrieve: permitted locators / revisions / risk signals
> compose: untrusted evidence / cited claims
> route: answer / clarify / deny / review
Untrusted document boundary

A document is evidence, not an instruction

Document-grounded assistants often receive files that were written for people: policies, tickets, manuals, emails and uploaded PDFs. Some of those files can contain text such as “ignore previous rules”, “reveal the hidden prompt” or “send this record to an external address”. That text is data from an untrusted source. It must not become an instruction merely because retrieval selected it.

This matters before generation. If an ingestion job preserves untrusted text beside system rules, or a prompt template gives retrieved passages the same authority as application policy, the model may follow a document's request instead of the product's intended workflow. A filter that looks for a few hostile phrases is useful as a signal, but it is not a security boundary.

The broad implementation and procurement scope belongs to RAG systems and /ai-specialist-armenia. This narrower guide describes a reviewable engineering boundary for one failure class; it does not certify an assistant as secure.

Define the trust contract before retrieval

Use an explicit contract for every stage. The application owns policy, tools and allowed actions. A user owns their request only within the current authorization boundary. A document owns neither permissions nor instructions, even when it is a current, trusted business source.

LayerCan influenceMust not influence
Application policyanswer format, tool allowlist, escalation routessource facts without retrieval
Authorized requesttask and permitted scopehidden policy, other users' data
Retrieved documentcited factual evidencetool calls, role changes, disclosure rules
Model outputproposed answer or safe routedirect side effect without an application gate

Store this contract next to a request receipt: caller role, collection and revision, retrieval query, returned locators, classifier signals, tool decision and final route. It gives a reviewer something better than a vague report that a “prompt filter ran”.

A small architecture with separate boundaries

DOC-GUARD-7 is a public synthetic architecture example. It has four decisions rather than one oversized prompt:

  1. Ingestion preserves the source, owner, revision, access label and a content-risk signal. It does not execute embedded instructions.
  2. Retrieval applies tenant and role filters before ranking. It returns locators and provenance, not authority.
  3. An answer composer labels passages as untrusted evidence and keeps application policy outside the document payload.
  4. An action gate validates structured intent against an allowlist, authorization and a human-review route before any consequential operation.
text
request -> authorize -> retrieve permitted locators -> inspect risk signal
        -> compose answer from untrusted evidence -> validate output intent
        -> answer | clarify | deny | human review

This separation is useful even when a document is benign. It lets the team ask a precise question: did the unsafe behavior arise from data lifecycle, access filtering, prompt composition, model output or an action integration? RAG access control covers the authorization boundary in more detail, while RAG citations and traceability explains why locators need to survive the answer.

Failure modes worth testing

Test an assistant with synthetic documents that resemble the source shapes it accepts. Do not put customer records or secret prompts in a public fixture. A useful test suite includes at least these routes:

Test caseExpected observationSafe route
A policy PDF says to ignore the application's safety rulespassage remains quoted evidence, not a commandanswer only from relevant facts or no-answer
An indexed support note asks to call an external URLno external call is proposed or executeddeny action; log locator
A retrieved record contains a tool-shaped JSON fragmentit remains text, not a tool invocationtreat as content; preserve provenance
A legitimate document is ambiguous or staleanswer cannot overstate the claimclarification, current source or review
A user asks for a prohibited recordretrieval does not expose the passagedeny before composition

Measure outcomes by route and consequence, not by a single “injection resistance” score. Record whether the document was retrieved, whether its instruction-like text reached the model, whether output asked for a tool, whether the gate denied it, and whether a reviewer could reproduce the result. The OWASP LLM Prompt Injection Prevention Cheat Sheet and NIST AI RMF Generative AI Profile were consulted on 2026-09-18 as guidance, not as a guarantee or a fixed implementation recipe.

Keep actions outside model authority

The critical mistake is allowing generated text to call a tool with whatever arguments it supplied. Instead, make the model produce a constrained proposal such as needs_human_review, cite_locator or draft_reply. The application then validates the proposal against a typed schema, caller entitlement, destination allowlist, rate limit and, where needed, an explicit human approval.

text
if riskSignal === "instruction_like" then route = "review";
if proposal.action not in allowedActions then route = "deny";
if proposal.references are not permittedCurrentLocators then route = "no_answer";
if consequence === "external_write" then require humanApproval;

The checks are deliberately independent. A benign-looking answer can still target the wrong tenant; a source can be current but not relevant; a model can format valid JSON for an action that no user is entitled to request. Fail closed for protected data and side effects, while keeping a usable clarification path for ordinary uncertainty.

Turn tests into a release gate

Run DOC-GUARD-7 when changing ingestion, chunking, retrieval filters, model, prompt template, tools or authorization integration. Keep a versioned set of synthetic adversarial documents, the source snapshot, expected routes and a receipt for each run. A missed access denial, unexpected tool proposal or uncited high-consequence answer should hold release until an owner classifies the cause and records the correction or accepted exception.

The point is not to promise that prompt injection has been solved. It is to make a document's power observable and bounded: it may supply cited evidence, but it cannot rewrite policy, expand access or trigger an action by itself. For a controlled architecture review, start with RAG systems or /ai-specialist-armenia.

CODE_BLOCK.TXT
require(request.authorized && retrieval.permittedLocators);
require(document.instructions !== application.policy);

if (riskSignal.instructionLike) route = "review";
if (!proposal.referencesArePermittedCurrentLocators) route = "no_answer";
if (!allowedActions.includes(proposal.action)) route = "deny";
if (proposal.consequence === "external_write") require(humanApproval);