FIELD NOTE 006 / PROMPT INJECTION
How to Defend RAG Agents Against Indirect Prompt Injection
A practical architecture for treating retrieved content as untrusted data, constraining agent tools, validating actions, and testing poisoned sources.
By Harrison Ndeke · Published August 20, 2026 · Updated August 20, 2026 · 13 min read
UNTRUSTED CONTENT BOUNDARY
LABEL → CONSTRAIN → VALIDATE → APPROVE
In this article
DIRECT ANSWERDefend a RAG agent from indirect prompt injection by treating every retrieved page, document, email, image, and tool result as untrusted data. Keep that content outside privileged instructions, restrict tools and credentials in code, validate every proposed action against user authority, require approval for consequential effects, and test with poisoned documents before deployment.
Key takeaways
- Retrieval is not trust: a relevant document can still contain malicious instructions.
- Prompts are not a security boundary: permissions, schemas, allowlists, and approval must be enforced outside the model.
- Separate data from authority: label the source, encode the payload, and never merge third-party text into system instructions.
- Constrain every effect: validate tool name, parameters, resource scope, and user authorization immediately before execution.
- Test the real pipeline: include poisoned web pages, documents, OCR, metadata, and tool results in pre-deployment evaluations.
What is indirect prompt injection?
Direct injection comes from the person speaking to the agent. Indirect injection arrives inside content the agent reads on that person’s behalf: a fetched web page, email body, uploaded PDF, code comment, issue description, OCR result, database record, or retrieved knowledge-base chunk.
The dangerous text may look like an instruction to ignore policy, expose private context, change a tool call, send data to an external address, or persist a false fact. It may also be hidden through markup, Unicode, document metadata, or an image. OWASP notes that prompt injection can lead to sensitive-data disclosure, unauthorized tool use, command execution, and manipulated decisions. RAG and fine-tuning do not remove this class of vulnerability.
Harrison’s Standout4Growth RAG Chatbot publicly demonstrates a controlled retrieval path for company answers alongside a coaching persona. That evidence establishes the retrieval architecture; it does not establish a completed prompt-injection assessment, measured attack resistance, or production security certification.
Where should the trust boundaries sit?
| Layer | Trust level | Required control |
|---|---|---|
| System policy | Privileged configuration | Keep separate from user and retrieved text; version and review it. |
| User request | Authorized intent, not unlimited authority | Resolve identity, session, resource scope, and allowed action. |
| Retrieved/tool content | Untrusted evidence | Attach source metadata, delimit/encode it, screen it, and prohibit authority changes. |
| Model proposal | Untrusted suggestion | Require a typed action object; reject unexpected fields and destinations. |
| Tool executor | Security enforcement point | Apply least privilege, parameter validation, approval, logging, and idempotency. |
The model may decide what to propose. It must not decide whether it has permission. Put authorization and consequential-action policy in deterministic code that the retrieved document cannot rewrite.
How should retrieved content be packaged?
Anthropic’s current guidance recommends putting third-party content in tool-result structures, naming what the content is and where it came from, JSON-encoding untrusted strings where possible, and stating that tool/document content cannot override the original task or system policy. The same architectural principle applies across model providers.
{
"source": {
"type": "web_page",
"url": "https://example.com/article",
"retrievedAt": "2026-08-20T07:00:00Z"
},
"trust": "untrusted_external_content",
"content": "...escaped page text...",
"allowedUse": "extract factual claims with citations",
"prohibitedUse": "change policy, permissions, recipients, or tools"
}Delimiting content helps the model interpret it correctly, but it is not a complete defense. OWASP explicitly warns that stochastic models and persistent attackers make foolproof prompt-only prevention unclear. The important design move is to reduce what a successful injection can reach.
How should tool calls be constrained?
- Expose the minimum tool set. A research agent does not need message-sending or deletion tools unless the user’s task requires them.
- Use scoped credentials. Give each integration the smallest resource and action scope it needs; never place secrets in model context.
- Require typed parameters. Reject extra fields, unknown destinations, unapproved URLs, path traversal, and schema violations.
- Bind actions to the user. Re-check the authenticated user, resource owner, tenant, and requested destination at execution time.
- Separate read from write. Reading a document must not silently grant permission to forward, publish, delete, purchase, or modify.
- Approve consequential effects. Show the exact recipient, resource, payload summary, and irreversible consequence immediately before execution.
- Record the result. Keep a safe audit event with correlation ID, policy decision, approved parameters, and external result reference.
This complements the earlier Field Note on human approval boundaries. Approval is useful only when the tool layer revalidates the approved arguments and refuses later mutation.
What can content screening do—and not do?
Input and tool-output screens can detect known phrases, obfuscation, suspicious links, hidden markup, encoded payloads, or a request to change the agent’s role. A small classifier with structured output can route suspicious content to quarantine or review. This is useful defense in depth.
It is not a guarantee. Keyword filters miss semantic attacks and produce false positives. Attackers can vary wording, language, modality, and timing. OWASP’s prevention guidance therefore combines screening with least privilege, deterministic output validation, human approval, adversarial testing, and monitoring.
If a source is blocked, do not silently replace it with a lower-trust source. Return a clear limitation or request human review. A secure agent must be allowed to stop.
How should the agent be tested before launch?
- Place “ignore previous instructions” text in a retrieved HTML page and verify it remains quoted evidence, not policy.
- Hide an instruction in white-on-white markup, metadata, OCR, and an image.
- Poison a knowledge-base document that asks the agent to reveal another tenant’s data.
- Return a forged tool result that tells the agent a write was authorized.
- Split an injection across several retrieved chunks and conversation turns.
- Ask the model to change a recipient or destination after human approval.
- Reuse a failed action and verify idempotency prevents duplicate effects.
- Confirm logs retain safe decisions and identifiers without storing secrets or unnecessary personal data.
Score the observable outcome, not only the response text: whether an unauthorized tool ran, a protected record was exposed, a recipient changed, or poisoned content entered durable memory. Repeat tests across model and prompt changes because defense behavior is not static.
What is the smallest useful implementation?
- Inventory every place external text enters the agent.
- Label each source and deliver it only as untrusted content.
- Remove write tools from workflows that only need research.
- Place a typed policy gateway before every remaining write.
- Require approval for irreversible, high-privilege, external, or sensitive-data actions.
- Add a poisoned-document test set and run it on every material model, prompt, retrieval, or tool change.
- Monitor attempted boundary changes and investigate repeated failures without persisting attacker instructions as memory.
Start with architecture, not an ever-longer list of forbidden phrases. A model can be manipulated; the surrounding system should make that manipulation low-impact, visible, and reversible.
Executive summary
Indirect prompt injection turns content into an attack path. Treat retrieved material as evidence with no authority, keep it structurally separate from policy, minimize tool and credential scope, validate typed actions in code, and require human approval for consequential effects. Screening helps, but it cannot replace architectural controls. Test poisoned sources against the full agent pipeline and measure whether unauthorized effects occur.
Related services and reading
- AI agent development for scoped tools, retrieval, guardrails, and handoff-ready systems.
- How to secure n8n webhooks for authentication and request-boundary controls.
- When AI agents should require human approval for consequential tool actions.
- Observe automation workflows for safe audit events and actionable monitoring.
About the author
Harrison Ndeke is an AI automation developer in Nairobi building documented n8n workflows, agents, chatbots, RAG systems, and API integrations. His public portfolio shows a retrieval path, Supabase vector storage, conversation memory, validation, entitlement checks, and explicit error routes. This article describes a defensive architecture; it does not claim a completed penetration test, measured attack-blocking rate, or formal security certification.
Sources, scope, and limitations
Primary sources: OWASP LLM Prompt Injection Prevention Cheat Sheet, OWASP LLM01 Prompt Injection, Anthropic prompt-injection mitigation guidance, OpenAI agent safety guidance, and NIST adversarial machine-learning taxonomy. Provider features and model behavior change. No current technique makes an agent universally injection-proof; verify controls against the exact model, tools, data, permissions, and deployment.