Zurück zum Blog
14. August 2026

Indirect Prompt Injection to Data Exfiltration: When the Model Has Tools

Viktor Bulanek
Founder & CTO, Penetrify
MSc IT Security · 20+ years in security · 4x Ex-CTO

Most writing about prompt injection stops at the model: can you make it ignore its instructions, can you extract the system prompt. Interesting, and rarely the incident. The incident is what happens next, when a model that has been persuaded can also act — through a tool, a function call or an MCP server holding credentials.

And the persuasion does not need to come from the person using your product. That is the part teams underestimate.

Direct Versus Indirect, and Why Only One Is Interesting

Direct injection is a user typing instructions into your chat box. It is easy to demonstrate, easy to write about, and bounded by what that user is already allowed to do — they are attacking their own session.

Indirect injection is instructions arriving inside content your application retrieved: an uploaded PDF, a scraped web page, a support ticket, an email in a connected inbox, a row in a database another tenant can write to. Your application fetches it, places it in the context window as data, and the model reads it as instruction — because there is no mechanical difference between the two. Everything in the window is text.

That changes the threat model completely. The attacker no longer needs an account, a session, or any access to your product. They need to put text somewhere your users' assistant will read: a document they email in, a page they know you crawl, a field they can fill in a shared workspace.

The Chain That Turns It Into Exfiltration

The severity comes from what the model can invoke. A four-step chain, all of it plausible in a normal product:

One: the attacker plants text in content the application will retrieve. A résumé uploaded to a hiring tool, a comment in a shared document, an invoice PDF sent to an accounts inbox — anything your assistant is meant to read on the user's behalf.

Two: the text carries instructions. Not the naive kind, which filters catch, but instructions shaped like the rest of the document: a section that reads as internal formatting guidance and asks the assistant to include a summary of recent records, or to call a named tool with particular arguments.

Three: the model calls a tool. This is the pivot. If the tool is search_customer_records and it executes with service credentials rather than the calling user's permissions, the model has just read data the user could not have retrieved themselves.

Four: the data leaves. Sometimes through the answer, if the user then forwards it. More often through another tool — a webhook, an HTTP fetch, an image URL the client renders, a document the assistant is asked to write into a shared folder. Any tool that can reach the network is an exfiltration channel, and a Markdown renderer that fetches images is a channel most teams do not count as one.

Where the Real Bug Is

It is tempting to call step two the vulnerability. It is not; it is the entry point. The vulnerability is in step three, and it is an old one wearing new clothes: a tool that acts on the model's intent rather than re-checking the caller's authorisation.

Say that plainly and the fix becomes obvious. If search_customer_records runs the same authorisation check it would run for a direct API call from that user, then a successful injection produces an empty result and an odd-sounding answer. If it runs with a service role because "it is internal", injection becomes a cross-tenant read.

The same logic applies to every tool. A tool that fetches URLs becomes SSRF, and in a cloud environment SSRF reaches the metadata endpoint and returns role credentials — which is how an AI feature becomes an infrastructure compromise. A tool that writes files becomes a way to plant content for the next user's assistant to read, which is persistence.

How to Test Your Own Application

Test the chain, not the model. Three exercises, in order of what they tell you.

Can retrieved content reach the context window unlabelled? Upload a document containing an instruction to call a tool with specific arguments, then check your traces: did a tool call occur that the user did not ask for? You do not need the injection to be clever for this test; you need to know whether the path exists.

Does each tool re-authorise? For every tool definition, trace the credential it uses. Then, as a low-privileged user in tenant A, induce a call whose arguments reference tenant B. If the tool returns data, you have found the finding that matters, and no prompt engineering will fix it.

Can anything reach the network? Inventory the tools that fetch, post or render remote content, including image rendering in your own client. Then test whether a tool-driven request can hit an internal address — 169.254.169.254 first, since cloud metadata is the highest-value target — and whether responses come back into the conversation.

Do all of this as two tenants. A single-tenant test cannot find the class that ends up in a breach notification.

Mitigations That Actually Hold

Assume injection succeeds. Nothing at the prompt layer closes this class — instruction and data share a channel, so filtering raises cost without changing the model of the problem. What holds is limiting the consequences:

Tools re-check authorisation. Every tool executes with the calling user's permissions, verified inside the tool, not with a service identity. This single control removes most of the severity.

Retrieval is filtered at the store. Tenant scoping belongs in the query to your vector database or search index, not in an instruction telling the model which documents it may use. An instruction is a suggestion; a filter is a boundary.

Egress is constrained. Tools that fetch URLs use an allow-list, refuse link-local and private ranges, and do not follow redirects into them. Client-side rendering of model output does not fetch arbitrary remote resources.

Consequential actions need confirmation. Anything that moves money, sends a message externally, deletes data or changes permissions goes through a human confirmation that shows what will happen — not a yes/no on an action the user cannot inspect.

Everything is logged as an action, not a chat. Tool calls with arguments, results and the identity they ran as. Without that trail you cannot answer the only question that matters after an incident: what did it do?

Why This Is Ordinary Application Security in New Vocabulary

Strip the language away and the finding reads: an internal function performs a privileged action based on untrusted input, without checking whether the caller is entitled to the result. That is a missing authorisation check. We have been finding it in web applications for twenty years; the model is a new caller, not a new class.

Which is the useful conclusion for anyone building AI features under time pressure. The novel parts — injection, retrieval, tool orchestration — need attention. But the majority of exploitable findings we see in AI applications are the boring ones: over-privileged tools, tenancy that leaks through retrieval, provider keys in a client bundle, unbounded cost. A team that treats AI security as an exotic discipline and skips the fundamentals ships the same IDOR everyone else does, with an LLM in front of it.

If you want the full scope of what testing an LLM-backed application involves, we describe it in AI application penetration testing.

Frequently Asked Questions

Welche Arten von Sicherheitslücken erkennt Penetrify?

Penetrify erkennt alle OWASP-Top-10-Schwachstellenkategorien, darunter SQL-Injection, XSS, CSRF, IDOR, fehlerhafte Authentifizierung, Sicherheitsfehlkonfigurationen und die Offenlegung sensibler Daten. Es testet auch die API-Sicherheit, das Session-Management und häufige Fehlkonfigurationen in Supabase, Firebase und Bubble.

Wie lange dauert ein KI-Penetrationstest?

Ein Quick-Scan ist in 15–30 Minuten abgeschlossen. Ein Standard-Scan läuft 1–2 Stunden mit breiterer Abdeckung. Ein Deep-Scan kann für komplexe Anwendungen mehrere Stunden dauern.

Was enthält ein Penetrify-Bericht?

Jeder Bericht enthält eine Executive Summary, einen Gesamtsicherheitsscore, nach Schweregrad klassifizierte Befunde (Kritisch, Hoch, Mittel, Niedrig), schrittweise Reproduktionsschritte und konkrete Abhilfemaßnahmen – geschrieben für Entwickler, nicht für Compliance-Beauftragte.

Related articles

Vulnerability Assessment vs. Penetration Testing: Was braucht Ihre App im Jahr 2026?
Was wäre, wenn die 15.000 Dollar, die Sie im letzten Quartal für ein Sicherheitsaudit ausgegeben haben, Ihre Benutzerdaten nicht wirklich geschützt hätten? Im Jahr 2024 berichtete IBM, dass die durchschnittlichen Kosten einer Datenschutzverletzung einen Rekordwert von 4,88 Millionen Dollar erreichten, aber 62 % der Technologieverantwortlichen haben immer noch Schwierigkeiten, den ROI ihrer Sicherheitstools zu definieren. Die Wahl zwischen einer Schwachstelle…
SQL Injection: Der umfassende Leitfaden zu Angriffen & Prävention
Dieses nagende Gefühl, wenn man sich fragt, ob die eigenen Datenbankabfragen wirklich sicher sind, kennen viele Entwickler nur allzu gut. Eine einzige, ungeprüfte Benutzereingabe kann für einen Angreifer ausreichen, um die Abwehrmechanismen Ihrer Anwendung auszuhebeln und ein simples Login-Formular in eine verheerende Datenpanne zu verwandeln. Diese Angst…
SQL Injection Prävention und Testing: Das Sicherheitsframework 2026
Was wäre, wenn Ihre Sicherheitslösung so präzise wäre, dass Ihr Release-Zyklus 2026 keine einzige manuelle Freigabe benötigen würde, um die Sicherheit zu gewährleisten? Sie haben wahrscheinlich schon die Frustration erlebt, wenn manuelles Penetration Testing Ihren Deployment-Zeitplan um 72 Stunden verzögert oder wenn Ihr aktuelles SAST-Tool 40 False Positives meldet für…

Explore more