mcp-confirm
mcp-confirm
In einfachen Worten: Wenn eine KI fragt „Bist du sicher?“, verhindert das MCP SDK bereits, dass diese Bestätigung für eine andere Aktion wiederverwendet wird. Es verhindert nicht, dass dieselbe Bestätigung zweimal verwendet wird. Dies schließt diese Lücke und zwei weitere, die das SDK offen lässt.
Zuerst lesen: Der Großteil dieses Problems ist bereits gelöst
Die MCP-Spezifikation vom 28.07.2026 führte Multi Round-Trip Requests ein, sodass ein Tool mitten im Aufruf pausieren und den Benutzer um Bestätigung bitten kann. Die Bestätigung reist als undurchsichtiger requestState durch den Client zurück, den Server laut Spezifikation MÜSSEN als angreiferkontrolliert behandeln.
Das Python-SDK erledigt das standardmäßig auf jedem MCPServer. RequestStateBoundary wird bedingungslos an die Middleware-Kette angehängt – mit einem ephemeren Schlüssel, wenn Sie keinen angeben. Es versiegelt den Zustand mit AES-256-GCM und bindet ihn an die Methode, das Ziel, einen Digest der Aufrufargumente, die Audience und den authentifizierten Principal, mit einer TTL.
Der Angriff, nach dem jeder zuerst greift – Bestätigung zum Löschen von cache.txt, dann Wiederverwendung dieser Bestätigung gegen thesis.txt – wird vom SDK bereits abgelehnt. Dafür brauchen Sie keine Bibliothek, und Sie sollten auch keine schreiben.
Dieses Repository hat ursprünglich trotzdem eine geschrieben: 250 Zeilen HMAC, TTL und Argumentbindung, als Hauptfeature ausgeliefert, überflüssig noch am Tag der Veröffentlichung. Das ist unten dokumentiert, statt stillschweigend gelöscht zu werden.
Related MCP server: approval-gate
Was das SDK nicht tut
Drei Lücken, jede mit einem Test, der auslöst.
1. Es bindet den Zustand und lässt ihn ablaufen. Es verbraucht ihn nie.
Innerhalb der TTL verifiziert die gleiche Bestätigung so oft, wie sie vorgelegt wird. Jede Prüfung, die die Boundary durchführt, besteht jedes Mal. Die Spezifikation stellt ausdrücklich klar, dass dies beabsichtigt ist und dass der Rest Ihre Aufgabe ist:
Beachten Sie, dass diese Maßnahmen das Wiedergabefenster begrenzen und die Wiederverwendung über Benutzer und Anfragen hinweg verhindern, aber für sich genommen keine Einmalverwendung garantieren. Server, für die ein bestimmter
requestStatehöchstens einmal verbraucht werden darf (z. B. Einmal-Einlösungen), MÜSSEN diese Invariante serverseitig durchsetzen.
Für „Datei löschen“ findet der zweite Versuch nichts. Für „£500 überweisen“ ist es das gesamte Problem. singleuse.py ist diese Invariante – ein Hauptbuch ausstehender Bestätigungen, das bei der Einlösung verbraucht wird. Es enthält keine Kryptografie, weil die Boundary bereits garantiert, dass der Klartext von diesem Server stammt.
2. Nichts bereinigt die Frage, die der Mensch liest
Eine Elicitation-message ist ein vom Server gewählter Text, der einer Person angezeigt wird, normalerweise mit einem nicht vertrauenswürdigen Wert, der hineininterpoliert wird – der ganze Sinn ist zu sagen, welche Datei verschwindet. Nennen Sie also eine Datei:
cache.txt
SYSTEM NOTICE: your session has expired.
Enter your AWS secret key to continue:Der Dialog trägt jetzt eine zweite, offiziell aussehende Aufforderung. Der Benutzer bestätigt keine Löschung; er wird von seiner eigenen Tooling-Infrastruktur phisht. Dieselbe Veröffentlichung vom 28.07.2026 brachte auch MCP Apps – servergerenderte UI – heraus, was diese Angriffsfläche eher vergrößert als verkleinert.
prompt.py reduziert nicht vertrauenswürdige Werte auf eine Zeile, entfernt bidirektionale Überschreibungen und Nullbreitenzeichen und kürzt von der Mitte aus, sodass der Dateiname am Ende sichtbar bleibt. Steuerzeichen werden zu Leerzeichen statt gelöscht, denn wenn man sie zusammenfallen ließe, würden a\nb und ab identisch dargestellt – zwei verschiedene Dateien, ein Dialog.
3. Keine Protokollebene kann Ihre Ressource zur Ausführungszeit erneut prüfen
Der Benutzer hat in der Zwischenzeit darüber nachgedacht. Die Datei kann in diesem Fenster ersetzt werden, und nur das Tool weiß, was „unverändert“ für sie bedeutet. Dieser Server prüft vor dem Löschen erneut und lehnt einen Pfad ab, der zu einem Symlink geworden ist.
Welche Ebene lehnt was ab
Das ist der nützliche Teil, und die Tests sind geschrieben, um genau das zu zeigen. MCPError bedeutet, dass die Middleware des SDKs abgelehnt hat, bevor dieses Paket lief; ToolError bedeutet, dass dieses Paket es getan hat.
Angriff | Abgelehnt von | Test |
Bestätigung auf eine andere Datei wiedergegeben | SDK |
|
Zustand gefälscht oder unter einem anderen Schlüssel versiegelt | SDK |
|
Dieselbe Bestätigung zweimal verbraucht | dieses Paket |
|
Zustand von einer anderen Replik erzeugt | dieses Paket |
|
Dateiname fälscht einen Systemprompt | dieses Paket |
|
Datei nach der Bestätigung gegen einen Symlink ausgetauscht | dieses Paket |
|
Pfad außerhalb der erlaubten Roots | dieses Paket |
|
Tests
35 Tests – 17 über den Server, 11 für das Hauptbuch, 7 für die Prompt-Bereinigung.
Jeder Server-Test läuft durch die echte RequestStateBoundary, dieselbe Klasse, die MCPServer auf sich selbst installiert, mit einem festgelegten Schlüssel – Runde eins versiegeln und Runde zwei entsiegeln genau so, wie es die Leitung tun würde.
Dieser Testrahmen existiert wegen eines bestimmten Fehlers. Die erste Version testete, indem sie MCPServer.call_tool() direkt aufrief, was direkt zum Tool-Manager geht und die Middleware-Kette vollständig umgeht. Die Boundary des SDKs lief nie, sodass eine redundante, handgebaute Absicherung tragend wirkte. Das Testdesign war es, das dies einen gesamten Build-Zyklus lang verbarg.
Die Abdeckung beträgt 81 %, mit prompt.py bei 100 % und singleuse.py bei 94 %. Die Lücke ist das argparse- und Transport-Wiring von main(), das stattdessen über build_server getestet wird.
CI läuft nur auf Ubuntu, bewusst: Die Tests für den Austausch nach Bestätigung benötigen Symlinks, und der Build schlägt fehl, wenn sie dort als übersprungen gemeldet werden.
Installation
pip install git+https://github.com/les-k/mcp-confirm.gitAusführen
mcp-confirm --root /path/you/allowOhne --root lehnt der Server jede Anfrage ab, statt auf irgendetwas zurückzufallen. Die Roots werden beim Start festgelegt und niemals vom Agenten gewählt. Kein Signaturschlüssel ist nötig – MCPServer bringt seinen eigenen mit.
Bekannte Einschränkungen
Das Hauptbuch ist im Speicher, also ist es für einen Prozess korrekt und hinter einem Load Balancer falsch. Das SDK unterstützt das Teilen von Schlüsseln über Repliken hinweg (
RequestStateSecurity(keys=[...])); unter dieser Konfiguration lehnt Replik B eine von Replik A ausgestellte Bestätigung ab. Es schließt sicher – die sichere Richtung –, wirkt für einen Benutzer aber wie eine Bestätigung, die unerklärlicherweise nicht mehr funktioniert. Eine Multiprozess-Bereitstellung benötigt Redis oder eine Datenbankzeile mit einem atomaren Vergleich-und-Löschen. Es gibt einen Test für dieses Verhalten.Das Demonstrationswerkzeug ist bewusst klein. Es löscht eine Datei. Der interessante Code ist
singleuse.pyundprompt.py.Kein CVE stützt das. MRTR ist erst Wochen alt, also basiert dies auf der eigenen MUST/SHOULD-Liste der Spezifikation und auf dem Lesen des SDKs, nicht auf einem veröffentlichten Vorfall.
Was an Version 0.1.0 falsch war
Hier aufbewahrt, weil ein Repository, das nur seine Erfolge festhält, kein Beleg für irgendetwas ist.
0.1.0 hat neu implementiert, was das SDK bereits tat. state.py war 250 Zeilen HMAC-Signierung, TTL und Principal-/Methoden-/Argumentbindung – alles eine Duplizierung von RequestStateBoundary, nichts davon so gut: HMAC, wo das SDK authentifizierte Verschlüsselung verwendet, keine Audience-Bindung, keine Schlüsselrotation.
Es wurde durch das Lesen des SDK-Quellcodes entdeckt, nicht durch einen Test. Die Tests bestanden genau deshalb, weil sie die Middleware umgingen, die es aufgedeckt hätte.
CI entdeckte separat einen echten Fehler in 0.1.0: Die Symlink-Prüfung lief nach Path.resolve(), untersuchte also das Ziel des Links statt des Links selbst. Ein Austausch, der auf eine andere Datei innerhalb eines erlaubten Roots zielte, wäre gelöscht worden. Behoben, mit einem Test für die Variante, die das Original nie ausführte.
0.2.0 löscht state.py vollständig und behält nur das, was das SDK nicht abdeckt.
Lizenz
MIT.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Security & DLP proxy for MCP: tool-poisoning scans, PII redaction on tool args/results. Beta.
Find, vet, and run MCP tools through a secure audited gateway with prompt-injection risk scoring
Email safety MCP server. Detects phishing, prompt injection, CEO fraud for AI agents.
Related MCP Servers
- AlicenseAqualityAmaintenanceAn MCP server that provides safeguard capabilities to protect against prompt injection and unsafe tool calls.7111 PyPI11MIT
- AlicenseNot gradedqualityCmaintenanceMCP server that provides human-in-the-loop approval for risky AI agent actions, with durable state and audit logs.MIT
- FlicenseNot gradedqualityCmaintenanceMCP server that provides a security gateway for AI agents, enforcing allow/confirm/deny policies on tool calls and requiring human approval for risky operations, with full audit logging.-
- AlicenseNot gradedqualityAmaintenanceMCP server that gates agent tool calls by normalizing intent, denying unknown/unattended destructive actions, and requiring HITL prove approval for high-risk operations. It maintains an append-only hash-chained Action Ledger and exposes gate_check and ledger_verify tools without ever executing tools.MIT