KI-Agenten-Sicherheit: Bösartiges JSON, Prompt Injection, Tool Calling und Risiken strukturierter Daten

Stand 14. September 2026: Sobald ein Agent Tools aufrufen und fremdes JSON lesen kann, wird aus einer falschen Antwort ein echter Aufruf. Defensive Karte zu bösartigem JSON, indirekter Injection, zu mächtigen Tools und zu lockeren Schemas.

Kurzfassung: 2026 ist KI-Agenten-Sicherheit nicht die Frage „sagt das Modell das Falsche?“, sondern „können nicht-vertrauenswürdige strukturierte Daten zu einem echten Tool-Aufruf werden?“ Ein injizierter Chatbot liefert schlimmstenfalls eine irreführende Antwort. Ein injizierter Agent schickt Mails, ändert Dateien, fragt eine Datenbank ab oder löst eine Zahlung aus. JSON ist Vertrag und Payload zugleich. Prompt Injection sitzt oft nicht in der Chatbox — sondern in Ticketfeldern, Webseiten, Mailkörpern und API-Antworten, die alle als JSON ankommen.

Stand 14. September 2026. Wir haben bereits behandelt, warum Tool Calling von JSON Schema abhängt, den Agent-JSON-Datenfluss, JSON Schema als Vertrag und MCP / Skills / Tools / Subagents. Dieser Text beantwortet nur, welches Risiko bösartiges JSON, indirekte Injection, überprivilegiertes Tool Calling und zu lockere Schemas jeweils tragen — und was der Host durchsetzen muss. Es ist ein Defensivleitfaden. Er liefert keine reproduzierbaren Angriffsschritte und keinen fertigen Injection-Text.

Eine Tabelle: Angriffsfläche Chatbot vs. Agent

Was der Nutzer tippt, ist nur ein Ausschnitt dessen, was ein Agent liest. Im Default-Stack 2026 liest das Modell außerdem Tool-Ergebnisse, MCP Resources, Seitenausschnitte, Ticketfelder und Mailkörper — fast immer als JSON oder als in JSON gewickelte Strings. Branchenlisten sortieren das unter Prompt Injection, Insecure Output Handling und Excessive Agency. Die Taxonomie braucht niemand zuerst. Entscheidend ist, wer spricht und wer ausführt.

DimensionChatbotAgent mit Tool-Aufruf
FehlerbildEine falsche oder gelenkte AntwortEin echter Seiteneffekt: schreiben, anfragen, Daten ändern
Nicht vertrauenswürdige EingabeDie aktuelle NutzernachrichtNutzertext + externes JSON + Tool-Ergebnisse + Seiten-/Mailfelder
AusführenderDas Modell emittiert nur TextHost / MCP Server führt arguments aus
VertragDer Prompt (weich)JSON Schema + Host-Validierung (hart)
Kleinster FixPrompt-Anpassungen, AblehnungsrichtlinieEngeres Schema, Tool-Allowlist, unabhängige Autorisierung

Ein Satz: das Modell kann getäuscht werden; der Host darf nicht mitausführen. Die Sicherheitsgrenze liegt zwischen dem Erzeugen von tool_calls und dem tatsächlichen Ausführen. Validierung, Autorisierung und Audit gehören dorthin — nicht „Modellausgabe als vertrauenswürdiges RPC behandeln“.

Bösartiges JSON: Extra-Felder, Typverwirrung, verschachtelte Payloads

Bösartiges JSON ist oft wohlgeformt und trotzdem gefährlich. Ein strikter Parser lehnt trailing commas oder Kommentare ab. Ein lockerer Parser, String-Konkatenation oder „erst Text, dann JSON.parse“ verschiebt den Fehler nur. In Agent-Systemen beginnt der Schaden, sobald der Host den Wert schon als Objekt behandelt.

Drei Formen, die zuerst zu härten sind (nur Muster — keine Anleitung):

MusterSo sieht es ausWenn der Host nicht validiertAbwehr
Extra-FelderEin Geschäftsobjekt mit nicht deklarierten KeysIn die Config gemerged oder an das nächste Tool weitergereichtadditionalProperties: false; unbekannte Keys verwerfen
TypverwirrungEin number/array kommt als string oder objectAuthz-Zweige schlagen fehl, oder ein ganzer Blob wird zum Argumenttype, enum, format festnageln
Verschachtelter PayloadEin String-Feld mit weiterem JSON oder einem langen BriefingInnerer Text landet im Prompt und wird als Anweisung gelesenLängenlimits; inneres JSON validieren; Rohtext nie als System-Sprache behandeln

Ein Tool-Parameter-Vertrag, der „funktioniert“, weil er fast nichts einschränkt — und die angezogene Fassung. Das sind Defensivbeispiele, kein Angriffsmaterial:

{
  "type": "object",
  "properties": {
    "payload": { "type": "object" }
  }
}

Dieses Schema ist fast kein Vertrag: jeder Key, jede Verschachtelung geht durch. In Produktion Felder auf eine Allowlist setzen und Extras verbieten:

{
  "type": "object",
  "properties": {
    "order_id": { "type": "string", "pattern": "^A-[0-9]{4,8}$" },
    "amount": { "type": "number", "minimum": 0, "maximum": 100000 },
    "note": { "type": "string", "maxLength": 200 }
  },
  "required": ["order_id", "amount"],
  "additionalProperties": false
}

Beim Review von Samples den JSON-Validator dieser Seite gegen dieses Schema nutzen und mit JSON Diff „arguments, die das Modell emittiert hat“ gegen „das kleinste Objekt, das Sie erlauben“ legen. Extra-Keys und gekippte Typen sind der erste Alarm.

Noch ein häufiger Fehler: nicht vertrauenswürdige Objekte nicht in interne Config oder Strukturen mergen, die an einer Prototypkette sitzen. In einem JavaScript-Host können unbekannte Keys in einem Config-Objekt mehr bedeuten als „ein Feld extra“. Der Fix ist derselbe: ein Allowlist-Objekt aus dem Schema projizieren, dann das weiterreichen.

Prompt Injection: Anweisungen in strukturierten Daten

Direkte Injection ist der Nutzer an der Chatbox, der den System-Prompt überschreiben will. Indirekte Injection entspricht, wie Agenten 2026 wirklich laufen: Anweisungen verstecken sich in Daten, die das Modell später liest — Tickettitel, Mailkörper, Seitenabsätze, PDF-Auszüge, JSON-Strings eines anderen Tools. Modelle trennen nicht von allein „Regeln, die der Entwickler schrieb“ von „Sätzen in den Daten“.

Strukturierte Daten machen das leiser. Eine Kundennotiz ist in der API nur customer_note. Im Kontext teilt sie den Token-Strom mit dem System-Prompt. Konkateniert der Host Tool-Ergebnisse ungefiltert in den nächsten Turn, schreibt eine externe Site oder ein Absender effektiv Prompts für den Agenten.

Abwehr ist nicht „bitte ignoriere bösartige Anweisungen“ als weiterer Satz. Prompts senken das Risiko; sie sind keine Grenze. Stabilere Kontrollen:

  • Herkunft kennzeichnen — externer Text kommt als eigene Rolle oder Wrapper (zum Beispiel tool / untrusted), nie in system gefaltet.
  • Sichtbare Fläche verkleinern — zusammenfassen statt einfügen; nur die nötigen Felder, nicht das ganze JSON-Dokument.
  • Hochwirksame Aktionen hinter ein Gate legen — Überweisungen, Löschen, Versand nach außen brauchen eine Policy-Engine oder einen Menschen, unabhängig vom Modell.
  • Tool-Ergebnisse als Daten behandeln, nicht als Anweisungen — Returns per Schema validieren, bevor sie wieder in den Prompt gehen.

Derselbe Impuls wie bei wie Apple Intelligence persönliche Daten schützt: was leakt oder missbraucht wird, ist oft ein Feld, das Sie in JSON gelegt haben. Im Modell kann ein Feld als Sprache gelesen werden; in Tool-Arguments als Aktion.

Tool Calling: Rechteausweitung, die wie ein gültiger Aufruf aussieht

Die Gefahr ist nicht „kann das Modell JSON emittieren?“. Sie ist, ob der Host das Modell als bereits autorisierten Aufrufer behandelt. Das klassische Confused-Deputy-Problem: das Modell schlägt vor; die Berechtigung gehört zu Nutzersitzung, Tenant und Service-Account. „export_orders aufrufen“ ist nicht dasselbe wie „dieser Nutzer darf die Tabelle exportieren“.

Überprivilegierung 2026 sieht oft so aus:

  • Ein einziges run_command / http_request mit fast beliebigen Strings;
  • Tools, die als Service-Account breiter als der Endnutzer laufen;
  • Der Host prüft JSON-Syntax, aber nicht „darf dieser Nutzer diese Ressource anfassen?“;
  • Nutzer- oder Seiten-JSON geht direkt als Tool-Arguments durch, ohne Ihr Schema.

Eine Deklaration, die zu offen ist, dann eine, die Sie wirklich reviewen können:

{
  "name": "fetch_url",
  "description": "Fetch any URL and return text.",
  "parameters": {
    "type": "object",
    "properties": {
      "url": { "type": "string" }
    },
    "required": ["url"]
  }
}
{
  "name": "fetch_public_doc",
  "description": "Fetch an allowlisted documentation URL.",
  "parameters": {
    "type": "object",
    "properties": {
      "doc_id": {
        "type": "string",
        "pattern": "^doc-[a-z0-9-]{1,32}$"
      }
    },
    "required": ["doc_id"],
    "additionalProperties": false
  }
}

Die zweite ist nicht „schlauer“. Sie macht aus einer offenen Fähigkeit einen auditierbaren Identifier. Der Host löst doc_id gegen die eigene Allowlist auf, setzt den Origin und legt Timeouts und Größenlimits fest. Das Modell sieht nie eine beliebige URL — ein Pfad weniger zu einer nicht vertrauenswürdigen Quelle.

Vor dem Ausführen drei Fragen: Steht dieses Tool auf der Sitzungs-Allowlist? Sind arguments durch Schema und Autorisierung unabhängig vom Modell gelaufen? Bei Fehler: ablehnen — oder Fehlerdetails als frischen injizierbaren Text zurückfüttern? Parameterfehler und Validierung beschreibt die Pipeline. Für Sicherheit zusätzlich: im Zweifel ablehnen, und das Modell nicht in einer unbegrenzten Schleife mit neuen Arguments retryen lassen.

Ein zu lockeres Schema ist eine Schwachstelle

Structured Output und Tool Calling nutzen beide JSON Schema, um illegale Tokens zu blockieren — der Default-Vertrag 2026, siehe was Structured Output ist. Schema garantiert Form, nicht sichere Bedeutung.

Lockere Verträge sehen meist so aus:

  • type: object ohne properties, oder additionalProperties bleibt true;
  • Ein Aktionsname, der ein Enum sein sollte, als beliebiger string;
  • Ein Identifier-Feld, das ein seitenlanges Briefing tragen kann;
  • Vendor-strict-Modus deckt eine Teilmenge ab, der Host nimmt an „die Modellseite hat schon alles blockiert“.

Zwei Tore stapeln: Schema auf der Modellseite reduziert Unsinn; der Host validiert noch einmal mit demselben (oder strengeren) Schema und projiziert dann in einen internen Typ. Vendor Structured Outputs ersetzen Ihre Autorisierung nicht. Feldunterschiede zwischen Vendors sind selbst Risiko — siehe den Structured-Output-Vergleich. Eine Migration, die den Vertrag lockert, vergrößert die Angriffsfläche.

Wenn Schema eine Sicherheitskontrolle ist, bevorzugen Sie enum, const, pattern, maxLength, minimum / maximum, required, additionalProperties: false. Brauchen Sie Freitext, isolieren Sie ihn, deckeln Sie ihn, und mappen Sie Freitext niemals auf einen Tool-Namen oder eine URL.

MCP und externe Tools: wo die Vertrauensgrenze liegt

MCP löst prozessübergreifende Entdeckung und Aufruf. Es löst nicht „ist dieser Server wohlwollend?“ Was MCP ist zeichnet die JSON-RPC-Linie schon: Modell-API auf der einen Seite, Host ↔ Server auf der anderen. Sicherheit braucht eine zweite Linie: Tool-Beschreibungen, Resource-Text und Rückgabe-JSON eines Drittanbieter-MCP-Servers sind nicht vertrauenswürdige Eingabe.

Das Risiko ist nicht das Protokolldatum. Es ist Vertrauen auf der falschen Schicht:

  • description / inputSchema aus tools/list in den System-Prompt geklebt;
  • result aus tools/call geht ungeprüft in den nächsten Turn;
  • Zu viele Server an einem Host, überlappende Namen oder Fähigkeiten, trotzdem Ausführung;
  • „Der Nutzer hat diesen Server erlaubt“ als „jeder Satz, den er zurückgibt, ist eine Anweisung“.

Skills haben dieselbe Problemklasse: ein Skill ist ein How-to, keine Authz-Schicht. SKILL.md aus einem nicht vertrauenswürdigen Repo zu laden, hängt einen Workflow an, dem das Modell folgt. Siehe was die vier Schichten besitzen — Schema nicht durch einen Skill ersetzen, und Rechteisolation nicht durch einen Subagent. Ein Subagent kann Tools verengen; der Elternprozess entscheidet weiter, welche Secrets er bekommt.

Defensiv-Checkliste: validieren, Allowlist, Least Privilege

Entlang des Ausführungspfads anziehen, von außen nach innen — nicht mit dem Prompt beginnen:

  1. Zuerst den Vertrag schreiben. Ein JSON Schema pro Tool: required vollständig, additionalProperties: false, Identifier über pattern / enum.
  2. Noch einmal auf dem Host validieren. Nicht vertrauen, „das Modell hat das Schema schon befolgt“. ajv oder gleichwertig; im Zweifel ablehnen.
  3. Projizieren; nicht durchreichen. Allowlist-Felder in ein internes DTO kopieren, dann die Business-API aufrufen.
  4. Tools minimieren. fetch_public_doc statt fetch_url; Read-only statt Write.
  5. Als Nutzer autorisieren, nicht als Modell. Session, Tenant und Resource-ACL in der Tool-Implementierung prüfen.
  6. Ausgehende Seiteneffekte hinter ein Gate legen. Senden, überweisen, löschen, Production-Deploy: Policy-Engine oder menschliche Bestätigung.
  7. Externen Text herabstufen. Tool-Ergebnisse, Seiten und Mails sind kein system. Wenn nötig, liefert ein read-only Subagent eine Zusammenfassung an den Eltern.
  8. Arguments auditieren. Tool-Name, validierte Parameter, wer autorisiert hat, ob abgelehnt wurde.

Prompts helfen trotzdem: sagen, dass Daten keine Anweisungen sind, verbotene Aktionen listen. Sie sind eine Hilfsschicht. Zehn weitere Prompt-Sätze ersetzen kein fehlendes Schema und keine ACL.

Verträge mit lokalen JSON-Tools prüfen

Vor dem Ship drei Dateien zusammen ansehen: die Tool-parameters / MCP-inputSchema, ein Happy-Path-Arguments-Objekt und ein bewusst hässliches Sample (Extra-Keys, falsche Typen, zu lange Strings). Keine echten Secrets, keine echten Nutzerdaten.

  • JSON-Validator — ist das Sample legales JSON, und erfüllt es Ihr Schema?
  • JSON Diff — was hat das Modell über das Minimalobjekt hinaus ergänzt?
  • Baumansicht — ist die Verschachtelung tiefer als sie sein sollte; verbirgt ein String-Feld eine weitere Struktur?

Nichts verlässt den Browser. Das passt zum Review eines Vertrags vor Produktion und zum Vergleich der Arguments eines fehlgeschlagenen Aufrufs. Feldnamen und required stabilisieren, dann Host oder MCP Server verdrahten.

FAQ

Kann JSON Schema Prompt Injection stoppen?

Nicht allein. Schema begrenzt Form und Wertebereich der Tool-Arguments und senkt die Chance, dass ein beliebiger String zu einer beliebigen Aktion wird. Indirekte Injection passiert, wenn Text in den Kontext eintritt — Sie brauchen weiter Herkunft, Herabstufung und Gates für hohe Wirkung.

Das Modell nutzt bereits Structured Output / strict mode. Muss der Host trotzdem validieren?

Ja. Vendor-Constraints gelten zur Generierungszeit, und jeder Vendor unterstützt eine andere Schema-Teilmenge. Sicherheitsentscheidungen müssen vor der Ausführung fallen, mit Ihrem eigenen Validator und Ihrer Autorisierung.

Was ist falsch daran, Nutzer-JSON direkt an ein Tool zu geben?

Sie überspringen den Vertrag. Extra-Felder, Typverwirrung und verschachtelter Text kommen unverändert in Code mit Seiteneffekten an. Validieren, dann projizieren; nur Allowlist-Felder weitergeben.

Darf die Ausgabe eines MCP Servers als System-Prompt dienen?

Nein. Beschreibungen aus tools/list, Resource-Text und tools/call-Ergebnisse sind nicht vertrauenswürdige Daten. Validieren, dann mit niedrigerem Privileg zurück in den Dialog.

Was ist die minimale Agent-Sicherheitsbaseline?

Striktes JSON Schema, Host-Zweitvalidierung, Tool-Allowlist, Autorisierung pro Nutzer und Gates für ausgehende Seiteneffekte. Ohne diese fünf den Agenten nicht an Produktionsdaten hängen.

Wie prüfe ich lokal, ob Tool-JSON gefährlich ist?

Schema und Argument-Samples in die JSON-Toolbox zur Validierung und Diff. required, additionalProperties und Längen-/Enum-Limits bestätigen, bevor Sie Host oder MCP Server verdrahten.

Fazit

Die Angriffsfläche des Agenten liegt zwischen strukturierten Daten und Tool-Ausführung: bösartiges JSON schlüpft am Vertrag vorbei, Prompt Injection lenkt die Absicht, Tool Calling macht Absicht zu Seiteneffekten, und ein lockeres Schema öffnet allen dreien die Tür. Der Default-Stack 2026 (Tools, MCP, Skills, Subagents) macht Agenten nützlicher — und macht „einen Aufruf täuschen“ wertvoller als „eine Antwort täuschen“.

Von innen nach außen verteidigen: JSON Schema zum harten Vertrag machen; der Host validiert, projiziert und autorisiert; Tools klein halten; externen Text nicht als Anweisung behandeln. Prompts helfen; sie sind nicht die Grenze. Samples lokal validieren vor dem Ship — Modelle können wechseln; Feldnamen, required und „wer darf ausführen“ sollten es nicht.