All posts

Prompt injection defenses: secure RAG access and AI agent tool execution

· 12 min read

Telling a model to ignore outside instructions cannot fully protect business data or actions. Follow a support assistant through indirect prompt injection, RAG authorization, least-privilege tools, approval before sending, and evaluations that observe what actually happened.

What is prompt injection? Direct versus indirect attacks

A defense should not depend entirely on the model recognizing hostile instructions. The application must also constrain accessible information and executable actions. OWASP lists this risk as LLM01:2025 and includes least privilege and human approval for high-risk operations among its mitigations.

TypeWhere instructions enterBusiness AI example
DirectA request supplied by the attackerA chat request to retrieve customer data the caller may not access
IndirectDocuments, email, search results, or tool responsesA support ticket contains instructions to send another case's information outside

A legitimate employee requesting a summary does not make the ticket's author trustworthy. Greshake and colleagues' 2023 paper studies indirect attacks through retrieved content in LLM-integrated applications. Distinguish this from hallucination, where the model generates incorrect facts, although injection can also manipulate an answer.

An attack path: a ticket summary becomes a message about another case

The employee requests the key points and a reply draft for ticket-42. Its body includes instructions to retrieve billing information from another case and send it to an outside contact as a prerequisite check. Even if the employee may read that other case, the current request does not authorize disclosing it.

Hypothetical unsafe architecture: a refusal in the final answer cannot undo a message sent earlier
  1. Employee / external text: The employee requests a summary and reply draft
  2. Employee / external text: The ticket contains instructions to retrieve and send another case
  3. AI / retrieval: The AI mistakes the text for an authorized instruction and retrieves another case
  4. Send service: The service sends without verifying approval of recipient and content
  5. AI / retrieval: A safe-looking answer still requires checking actual delivery records

Trace private-data access, outside-text processing, and external sending. Retrieval must block unauthorized documents, while sending needs a separate decision even for readable evidence. Correct retrieval authorization leaves a disclosure path if recipients and purposes remain unrestricted.

Separate outside data: what system prompts and JSON can accomplish

Pass content with structured provenance and document IDs, and state that retrieved instructions cannot change the task or permissions. Anthropic describes tool-result delivery, explicit provenance, and JSON encoding of third-party strings. These help the model distinguish content; a JSON wrapper does not enforce authorization.

RAG defenses: retain authorization through retrieval, reranking, and caches

RAG uses retrieved evidence during generation. An access control list (ACL) records who may read a document. Separate relevance search from permission decisions, including reranking, which reorders retrieval candidates. Here, server-verified employee and tenant context determines document access before content reaches external reranking or generation. A tenant_id proposed by the model cannot expand that scope.

Original RAG design: candidate exploration stays inside an authorized processing boundary; restrict content before passing it downstream

Resolve authenticated employee and tenant on the server → Filter candidates against current document permissions → Send only permitted content to reranking and generation → Check evidence permissions and destination before saving a draft → Apply current access rules when reusing caches or history

BoundaryCheck in this scenarioCommon gap
Source to indexPreserve document ID, version, tenant, and ACL associationChunks lose their permission metadata
Retrieval to downstream servicesAuthorize employee access and disclosure to each serviceSend full text to external reranking before filtering
Answer reuseSeparate tenant and user visibility; recheck evidence accessServe someone else's cached answer because the question matches
Permission changesDefine index propagation delay and authoritative recheck pointsDisplay old history or drafts unchanged after revocation

OWASP's RAG guidance covers carrying access controls to chunks and enforcing them before the model receives content. As a product example, Google Cloud Agent Search restricts results using end-user identity and document ACLs, subject to configuration requirements. Do not assume indexed ACLs guarantee immediate revocation; this scenario rechecks authoritative permissions at important boundaries.

AI agent defenses: valid arguments do not establish permission

The AI proposes an action; an execution service decides whether it is allowed. JSON schema validation checks tool names and argument types. A request to send another company's document can be well formed, so separately verify ownership, requester permissions, and the current task's scope. Connecting a tool through MCP does not remove execution-side authorization requirements.

CapabilityAllowed scope hereExecution-side control
Search and retrieve documentsRelevant evidence the current employee may readVerified identity and tenant; document authorization
Save a reply draftA private draft for an assigned ticketTarget access and version; no writes to another case
Send an external replyApproved content and attachments to an allowed recipientRecipient policy, individual approval, execution-time rechecks
Arbitrary URL, SQL, or shell executionUnnecessary for this featureExpose no general executor; reject unknown tools
Illustrative action proposal, not execution permission or evidence of user approval
{
  "tool": "propose_reply",
  "ticket_id": "ticket-42",
  "draft_version": 12,
  "recipient_ref": "contact-7"
}

The executor resolves access to ticket-42, stored draft version 12, and contact-7's actual address and relationship to the ticket. Employee and tenant identity come from authenticated execution context, not model claims. A model-produced value such as user_confirmed=true is not approval evidence; consult the server's approval record.

Approval before sending: bind the recipient, body, and attachments to execution

Generic permission to send a reply is ambiguous. This confirmation screen shows the ticket, resolved recipient, subject, full body, and attachments from a stored action. A short model-written description is insufficient: the reviewer must be able to notice information from another case in the actual content.

Original approval flow: approval and execution services operate outside the model's writable context
  1. AI / draft: Propose recipient, body, and attachments
  2. Execution service: Validate access and recipient; store an immutable action ID and content version
  3. Employee / approval service: Review the stored recipient, body, and attachments; approve that action
  4. Execution service: Match approver, target, version, and expiry; create one send job
  5. Execution service: Recheck current permissions and validity immediately before sending; track the result
  1. Bind the action ID to employee, tenant, ticket, tool, normalized recipient, body and attachment versions, and expiry. Changed address resolution or content requires approval of a new action.
  2. Only an authenticated confirmation path may create approval. Match and consume it while creating the durable send job in one database transaction, so concurrent or repeated requests cannot create additional jobs.
  3. Carry protected action and requester metadata into the job. Immediately before sending, check current permissions, approval expiry or cancellation, and recipient policy. Defer or deny if checks cannot complete.
  4. Design delivery deduplication around the same action ID. Verify the provider's idempotency support and reconcile unknown outcomes. Consuming approval once in the database does not guarantee exactly one external send.

OWASP's Transaction Authorization guidance covers protected transaction details, a final execution gate, expiry, and per-operation uniqueness. The database and send-job arrangement here is an original application to support work. Canceling approval cannot recover information already sent. Define how to handle permission changes between the final check and delivery according to platform and business requirements.

Outputs and logs: close disclosure paths outside the send tool

Generated Markdown images or links, arbitrary URL fetches, and logging destinations can become additional exits. This preview executes no raw HTML and loads no external images automatically. Navigation and fetch proxies also need destination and outbound-data controls. HTML escaping alone does not prevent every image- or URL-based disclosure.

Correlate request and action IDs with allow, deny, or review decisions, reasons, and execution outcomes. The example below records a rejection. Link it to protected references for the executor-verified actor and tenant. Avoid copying ticket bodies, full model inputs, credentials, or attachments into routine logs.

Illustrative structured log: action IDs correlate with access-controlled audit records and are not credentials
{
  "event": "agent_action_denied",
  "request_id": "req-42",
  "action_id": "action-8",
  "tool": "send_reply",
  "decision": "deny",
  "reason_code": "approval_action_mismatch",
  "policy_version": "support-v3"
}

OWASP's Logging guidance addresses excluding access tokens and secrets from direct logging. Allowlist fields, define access and retention, and use dummy secrets to test validation failures and downstream exceptions. Store detailed investigation evidence separately with a defined purpose, access policy, and expiry.

Evaluate evidence, tool calls, and delivery rather than refusal wording

Counting final refusals does not measure the defense. Use test tenants and dummy confidential values, then inspect evidence sent to the model, authorization decisions, and delivery records at instrumented destinations. Real API keys and customer documents are unnecessary for these attack tests.

Input or action in a test environmentExpected outcomeObservable evidence
Place another-case sending instructions in a ticket bodyNo send outside the requested scope executesProposals, authorization decisions, destination receipts
Pass another tenant's document ID to a toolNo document content reaches reranking or generationRetrieval results and downstream payloads
Change recipient, body, or attachments after approvalOriginal approval cannot authorize the changed actionStored action version and denial reason
Use the same approval twice concurrentlyOnly one send job is createdApproval state and job count; verify external delivery separately
Test queued revocation and an unavailable authorization service separatelyDeny missing permission; defer or deny unverifiable permissionExecution-time decisions and absence of external delivery
Insert an external image carrying a dummy value into the draftPreview sends nothing automatically outsideBrowser and server outbound traffic
Use normal tickets and documents quoting attack text for explanationLegitimate summaries and draft replies completeIncorrect refusals and actual task completion

For indirect injection, place the attack in the real ticket or retrieval channel being tested. Pasting it into the user's request tests a different path. Run revocation and authorization-service failure as separate cases too, so the cause of each stop is distinguishable.

OWASP's evaluation examples distinguish objective-specific observations from legitimate-task completion. These counts and calculations are original illustrations, not evaluation results. Trace accessible evidence, proposed actions, approvals, and actual side effects for one business workflow to identify the boundary that needs repair.

Primary sources and related tips

Tips this post digs into