7 Min. Lesezeit

Schwächen MCP-Fähigkeits-Downgrades die Kontrollen für Agenten?

MCP-Fähigkeits-Downgrades brauchen Sicherheitstests, die belegen, dass Freigaben, Prüfungen pro Aufruf und manipulationssichere Audit-Erfassung auch bei älteren Clients erhalten bleiben.

Schwächen MCP-Fähigkeits-Downgrades die Kontrollen für Agenten?

Protokollkompatibilität gehört zur Angriffsfläche. Wenn ein MCP-Client eine ältere Version aushandelt oder eine Fähigkeit weglässt, sollte er Komfortfunktionen verlieren, nicht die Kontrollen, die verhindern, dass ein Agent mit der Berechtigung einer anderen Person handelt.

Ich habe erlebt, wie dieser Fehler als harmlose Kompatibilitätsänderung auftauchte: Ein Client kündigt eine Benachrichtigungsfunktion nicht an, also nimmt der Code einen alten Zweig. Dieser Zweig wurde geschrieben, bevor es eine Freigabe pro Sitzung gab. Eine Aktion rutscht durch, weil niemand diesen Zweig als Autorisierungspfad behandelt hat. Der Code besteht weiterhin die Happy-Path-Tests. Er ist trotzdem falsch.

MCP-Fähigkeits-Downgrades brauchen Sicherheitstests, weil sich die Initialisierungsmetadaten bereits vor der ersten sensiblen Anfrage des Agenten auf den Weg durch das Gateway auswirken. Teste diesen Weg wie ein Angreifer: Gib eine ältere Protokollversion an, lass Felder weg, sende ein leeres Fähigkeitsobjekt, starte den Prozess neu, sperre den Tresor, widerrufe die Sitzung und prüfe anschließend, was im Audit-Journal steht. Wenn sich die Antwort von „ablehnen oder fragen“ zu „ausführen“ ändert, ist Kompatibilität zu einer Umgehung der Zugangskontrolle geworden.

Ein Downgrade ändert den Weg, nicht die Berechtigung

Ein Kompatibilitätspfad kann Nachrichtenformate, verfügbare Benachrichtigungen, die Fortschrittsbehandlung oder den Umfang des Kontexts ändern, den der Client erhält. Er darf nicht ändern, wer eine Zugangsinformation verwenden darf oder ob ein Mensch den Aufruf freigeben muss.

Das klingt selbstverständlich, bis der Code beginnt, anhand von protocolVersion oder capabilities zu verzweigen. Ein Entwickler schreibt den Zweig oft, damit keine nicht unterstützte Servernachricht gesendet wird. Später legt jemand Sitzungsaufbau, Zustellung der Freigabe oder Initialisierung des Audits in denselben Zweig, weil diese Stellen gerade in der Nähe liegen. Das Downgrade verändert dadurch versehentlich eine Sicherheitsgrenze.

Die MCP-Spezifikation definiert die Initialisierung als Austausch, bei dem der Client eine Protokollversion und Fähigkeiten angibt und der Server mit seiner eigenen Version und seinen eigenen Fähigkeiten antwortet. Behandle diese Felder als Behauptungen eines nicht vertrauenswürdigen Kommunikationspartners. Sie können die Interoperabilität steuern. Sie dürfen keine Berechtigungen verleihen.

Sallyport macht diese Trennung praktisch: Tresortor, Sitzungsautorisierung und Schlüsseleinstellung pro Aufruf liegen unterhalb der MCP-Unterhaltung. Ein Agent kann daher nicht allein dadurch eine Zugangsinformation erhalten, dass er sich als älterer Client beschreibt. Das ist die richtige Struktur, braucht aber weiterhin Regressionstests an der Protokollgrenze.

Schreibe die Sicherheitsinvariante, bevor du die Matrix erstellst:

Für jede akzeptierte Variante der MCP-Initialisierung wird eine geschützte Aktion bei gesperrtem Tresor abgelehnt. Ein neuer Client-Prozess braucht eine Sitzungsfreigabe. Eine Zugangsinformation, die für die Prüfung pro Aufruf markiert ist, muss bei jeder Verwendung geprüft werden. Die Aktion erzeugt ein Audit-Ereignis, unabhängig davon, ob sie erfolgreich ist, fehlschlägt oder abgelehnt wird.

Dieser Satz gibt Reviewern etwas Präziseres als „Legacy-Clients funktionieren“. Ein Legacy-Client funktioniert nur, wenn er diese Ergebnisse beibehält.

Initialisierungseingaben brauchen feindselige Testfälle

Ein ordnungsgemäßer Client sendet einmal eine saubere Initialisierungsanfrage, listet die unterstützten Fähigkeiten auf und macht nach Erhalt der Antwort weiter. Sicherheitstests sollten dort beginnen und dann eine Annahme nach der anderen entfernen.

Verwende ein kleines Client-Fixture, das rohe JSON-RPC-Nachrichten senden kann, statt einer übergeordneten MCP-Bibliothek, die für dich Standardwerte ergänzt. Bibliothekstests sind nützlich, verbergen aber die Bedingungen auf der Leitung, die Downgrade-Fehler auslösen.

Eine Basisanfrage könnte so aussehen:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "CURRENT_TEST_VERSION",
    "capabilities": {
      "roots": { "listChanged": true },
      "sampling": {}
    },
    "clientInfo": { "name": "compat-fixture", "version": "1.0" }
  }
}

Das Fixture sollte anschließend Varianten erzeugen, die sich jeweils nur in einem wesentlichen Punkt unterscheiden:

  • die älteste unterstützte Protokollversion
  • die aktuelle Version mit {} als Fähigkeiten
  • die aktuelle Version ohne capabilities, falls dein Parser das akzeptiert
  • ein Fähigkeitsobjekt, in dem bekannte optionale Einträge fehlen
  • eine nicht unterstützte ältere Version, die der Server ablehnen muss

Kombiniere nicht alle Auslassungen im ersten Test. Wenn eine kombinierte fehlerhafte Anfrage scheitert, lernst du sehr wenig. Fälle mit nur einer Veränderung zeigen dir, welcher Standardwert oder Zweig das Ergebnis verändert hat.

Prüfe bei jedem akzeptierten Fall das gleiche Ergebnis für die geschützte Aktion vor der Freigabe. Die genaue Transportantwort hängt von der Implementierung ab, aber ihre Form muss eindeutig sein:

{
  "jsonrpc": "2.0",
  "id": 7,
  "error": {
    "code": -32001,
    "message": "Session authorization required"
  }
}

Prüfe nicht nur den Text. Prüfe eine stabile Fehlerkategorie oder einen internen Ergebnisscode, dass kein ausgehender HTTP-Aufruf oder SSH-Aufruf erfolgt und dass ein Audit-Eintrag für den abgelehnten Versuch existiert. Eine freundliche Fehlermeldung mit einem echten Seiteneffekt dahinter bedeutet: Test fehlgeschlagen.

Der schwierige Fall ist eine Initialisierungsanfrage, deren Felder zwar geparst werden können, aber nicht sinnvoll zusammenpassen. Vielleicht gibt der Client an, eine von deinem Server erkannte Version zu sprechen, erklärt aber keine der Fähigkeiten, die ein normaler Client dieser Version verwenden würde. Dein Gateway muss den Client nicht belehren. Es muss einen sicheren Weg wählen: die eingeschränkte Sitzung akzeptieren und alle lokalen Kontrollen beibehalten oder die Initialisierung ablehnen. Es darf nicht stillschweigend einen ungeschützten Weg wählen, nur weil die übliche Darstellung der Freigabe nicht verfügbar ist.

Alte Übertragungsformate dürfen kein altes Sicherheitsmodell erzeugen

Teams sagen oft, sie unterstützten eine ältere Protokollversion, wenn sie damit meinen, dass sie deren Nachrichten noch parsen können. Das ist nur die halbe Arbeit. Du musst außerdem entscheiden, welches aktuelle Sicherheitsverhalten erhalten bleibt, wenn das ältere Übertragungsformat kein entsprechendes Feld dafür besitzt.

Die Antwort sollte normalerweise lauten: alles. Sitzungsautorisierung ist lokaler Zustand. Die Prüfung pro Aufruf ist lokaler Zustand. Die Audit-Erfassung ist lokaler Zustand. Nichts davon setzt voraus, dass der Client ein gleichwertiges Feld in einer älteren Anfrage überträgt.

Hier verschwimmen Aushandlung von Fähigkeiten und Autorisierung. Ein Client kann eine Funktion zum Empfangen strukturierter Statusaktualisierungen nicht besitzen. Das sagt dir, wie du den Status der Freigabe mitteilst, nicht, ob du sie auslassen darfst. Wenn dein Produkt dem Benutzer für diesen Aufruf keine Prüfung anzeigen kann, lehne den Aufruf mit einer klaren Fehlermeldung ab. Einen Client darum zu bitten, zu versprechen, dass er eine Eingabeaufforderung angezeigt hat, ersetzt keine lokale Entscheidung.

Vermeide den beliebten Fallback „die gesamte Sitzung freigeben, wenn der Client Prüfungen pro Aufruf nicht verarbeiten kann“. Er ist beliebt, weil er Reibung beseitigt und eine Demo bestehen lässt. Er ist falsch, weil er die Entscheidung des Besitzers der Zugangsinformation für jede Verwendung ohne dessen Zustimmung in eine einmalige Entscheidung verwandelt. Die Einstellung der Zugangsinformation hat Vorrang.

Halte den Versionsadapter schlank. Er sollte Syntax von Anfrage und Antwort übersetzen, Nachrichten herausfiltern, die der Kommunikationspartner nicht versteht, und kompatible Fehlerformen abbilden. Er sollte nicht entscheiden, ob eine Aktion ausgeführt wird. Lege die Autorisierung in einen einzigen Pfad, den jeder Adapter aufruft.

Eine nützliche Frage im Code-Review lautet: Kann ein Kompatibilitätszweig ein Ausführungs-Handle, einen injizierten Autorisierungs-Header oder ein SSH-Ergebnis zurückgeben, ohne zuerst dieselbe Autorisierungsfunktion wie der neueste Client zu durchlaufen? Wenn ja, braucht dieser Zweig jetzt einen Test und bald eine Neugestaltung.

Die Sitzungsfreigabe muss dem anfragenden Prozess folgen

Eine Freigabe pro Sitzung lässt sich leicht falsch testen. Wenn der Testclient einen Prozess am Leben hält, ihn freigibt und zehn Aufrufe ausführt, beweist du nur, dass eine funktionierende Sitzung freigegeben bleibt. Du hast nicht bewiesen, dass der nächste Agent-Prozess seine eigene Entscheidung braucht.

Starte zwei unabhängig gestartete Fixture-Prozesse. Gib ihnen denselben angezeigten Clientnamen, dieselbe Protokollversion und dieselbe Fähigkeitsdeklaration. Prozess A initialisiert sich und fordert eine geschützte Aktion an. Gib seine Sitzung frei. Danach initialisiert sich Prozess B und fordert dieselbe Aktion an.

Prozess B muss eine neue Freigabeanforderung erhalten. Er darf die Autorisierung von A nicht übernehmen, nur weil er eine Clientbezeichnung, ein Arbeitsverzeichnis, einen Transportendpunkt oder ein zwischengespeichertes Verbindungsdetail teilt. Wenn deine Implementierung die Codesignatur-Berechtigung auf der Freigabekarte anzeigt, prüfe, dass die Karte die Prozessberechtigung ausweist, die B tatsächlich gestartet hat. Lass den Test nicht die dekorativen Teile der Karte prüfen. Prüfe das Identitätssignal, das ein Mensch für seine Entscheidung verwendet.

Teste anschließend die Lebenszyklusgrenzen, die Agenten in der Produktion erreichen:

  1. Gib Prozess A frei und lass ihn normal enden. Starte Prozess B mit identischen Metadaten. B muss eine Freigabe benötigen.
  2. Gib A frei und beende ihn anschließend ohne sauberes Herunterfahren. Starte B. B muss eine Freigabe benötigen.
  3. Gib A frei, widerrufe A während des laufenden Prozesses im Sitzungsjournal und führe danach von A einen weiteren Aufruf aus. Dieser Aufruf muss vor der Ausführung stoppen.
  4. Widerrufe A, während seine erste Aktion auf eine externe Antwort wartet. Die ausstehende Aktion darf nach dem Widerruf keine zweite freigegebene Aktion erzeugen.

Der dritte und vierte Fall zeigen einen häufigen Fehler: Das System prüft die Freigabe nur beim Öffnen einer Verbindung oder nur beim Erstellen eines Aktionsobjekts. Eine Sitzung kann sich ändern, während ein Prozess weiterläuft. Prüfe die Berechtigung an dem Punkt, an dem das Gateway die ausgehende Aktion verbindlich startet.

Verwende keine vom Aufrufer gelieferte Sitzungs-ID als Freigabeschlüssel. Ein Test kann diesen Fehler deutlich machen: Lass B die Sitzungsbezeichnung von A wiederverwenden und beweise, dass das Gateway trotzdem fragt. Ein Clientname ist eine Kennung für Anzeige und Diagnose, kein Beweis dafür, dass dieselbe ausführbare Datei erneut anfragt.

Die Prüfung pro Aufruf gehört zur Verwendung der Zugangsinformation

SSH auch bei alten Clients schützen
SSH-Aktionen laufen über den mitgelieferten `sp-ssh`-Helper, sodass Agenten keine SSH-Schlüssel besitzen.

Eine Einstellung für die Prüfung pro Aufruf bedeutet, dass das Gateway jedes Mal um Zustimmung bittet, wenn diese Zugangsinformation verwendet wird. Sie bedeutet nicht „einmal pro Toolname“, „einmal pro geöffneter Verbindung“ oder „einmal, außer der Client ist alt“. Gegenstand der Prüfung ist die tatsächliche Anfrage, die das Geheimnis übertragen oder den SSH-Schlüssel verwenden wird.

Erstelle einen Test mit einer Zugangsinformation, die für die Prüfung pro Aufruf markiert ist, und einem Fixture, das zwei gleichwertige Aktionen innerhalb einer bereits freigegebenen Sitzung sendet. Verwende für HTTP zwei Aufrufe an einen Testendpunkt, der eine harmlose Markierung zurückgibt. Verwende für SSH zwei harmlose Befehle auf einem isolierten Test-Host. Der Test sollte zwei getrennte Prüfereignisse und zwei getrennte Aktionsdatensätze beobachten.

Eine minimale erwartete Ereignisfolge sieht so aus:

session_authorized process=fixture-A
call_review_requested action=41 credential=deploy-token
call_completed action=41 result=success
call_review_requested action=42 credential=deploy-token
call_completed action=42 result=success

Die wichtige Aussage betrifft nicht die Nummerierung. Entscheidend ist, dass Aktion 42 die für Aktion 41 erteilte Freigabe nicht verwenden kann. Lass die zweite Anfrage nach Abschluss der ersten eintreffen und erstelle anschließend einen weiteren Fall, in dem beide fast gleichzeitig eintreffen. Nebenläufigkeit deckt Implementierungen auf, die ein vorübergehendes „Prüfung bestanden“-Bit an der Sitzung statt an einer einzelnen Aktion speichern.

Wiederhole den Test nun mit einer älteren Protokollangabe und mit weggelassener Fähigkeit, die dein normaler Pfad für den Prüfstatus verwendet. Der Prüfmechanismus kann auf dem lokalen Rechner anders dargestellt werden, aber das Ergebnis muss gleich bleiben. Wenn ein Benutzer die zweite Prüfung schließt, abbricht oder ablaufen lässt, darf der Testendpunkt nur eine Anfrage sehen, nicht zwei.

Halte eine harte Aussage zur Geheimnisoffenlegung fest. Die MCP-Antwort darf das Aktionsergebnis, einen Fehler oder den Status „Prüfung erforderlich“ enthalten. Sie darf keinen API-Schlüssel, keinen privaten SSH-Schlüssel, keinen redigierten Platzhalter anstelle des Geheimnisses und keinen Toolparameter enthalten, mit dem der Agent das Geheimnis rekonstruieren kann. Ein Downgrade ist ein naheliegender Ort, an dem ein Kompatibilitätsadapter zusätzlichen Kontext serialisieren könnte. Prüfe den rohen Mitschnitt, nicht nur dein strukturiertes Testobjekt.

Die Audit-Erfassung gehört unter die Protokollverhandlung

Ein Audit-Journal, das nur erfolgreiche Aufrufe moderner Clients aufzeichnet, ist ein Beruhigungsmittel. Die Fälle, die du später brauchst, sind abgelehnte Aufrufe, abgebrochene Prüfungen, abgelehnte Initialisierungsanfragen und seltsame Kompatibilitätspfade, bei denen ein Entwickler sagt: „Das dürfte niemals passieren.“

Erfasse die Fakten, die zur Rekonstruktion der Entscheidung nötig sind: Agent-Lauf oder Sitzung, Aktionsidentität, Kanal, angefordertes Ziel, Referenz oder sichere Kennung der Zugangsinformation, Autorisierungsstatus, Ergebnis der Prüfung und Ausführungsergebnis. Vermeide es, das Geheimnis selbst zu speichern. Bei einer fehlgeschlagenen Initialisierung solltest du genügend Kontext zum Kommunikationspartner und zum Parsing erfassen, um die Ablehnung zu erklären, ohne das Journal in eine Kopie nicht vertrauenswürdiger Nutzdaten zu verwandeln.

Sallyport erzeugt seine Journale für Sitzungen und Aktivitäten aus einem einzigen verschlüsselten, hashverketteten Audit-Log. Dieses Design ist für Downgrade-Tests wichtig, weil die Fähigkeiten des Clients nicht darüber entscheiden dürfen, ob ein zweites Journal existiert. Derselbe Schreibpfad sollte einen aktuellen Client, einen unvollständigen Client und einen abgelehnten Aufruf sehen.

Verwende nach jedem End-to-End-Fall die Offline-Prüfung der Kette als eine Aussage:

$ sp audit verify
verified: 18 records
chain: intact

Der genaue Wortlaut kann abweichen, aber der Test muss ein erfolgreiches Prüfergebnis verlangen, ohne den Tresor zu öffnen. Dieser Test erkennt einen fehlerhaften oder fehlenden verketteten Schreibvorgang. Er beweist nicht, dass das richtige Ereignis geschrieben wurde. Kombiniere ihn daher mit einer Abfrage der Ansichten für Sitzungen und Aktivitäten, die die erwarteten abgelehnten, freigegebenen, abgebrochenen oder abgeschlossenen Einträge prüft.

Teste auch die Reihenfolge. Wenn eine Prüfung abgelehnt wird, sollte das Journal die Anfrage und die Ablehnung zeigen, aber keinen erfundenen Abschluss. Wenn die Transportaktion nach der Freigabe fehlschlägt, erfasse diesen Fehler als Ausführungsfehler, nicht als Autorisierungsablehnung. Das sind unterschiedliche operative Fragen. Ihre Vermischung erschwert die Untersuchung von Vorfällen und lässt einen fehlerhaften Adapter wie eine Benutzerentscheidung aussehen.

Baue die Kompatibilitätsmatrix um Sicherheitsergebnisse herum

Jede Verwendung prüfen
Markiere einen Schlüssel für die Prüfung pro Aufruf. Sallyport fragt dann vor jeder einzelnen Verwendung der Zugangsdaten nach.

Ein vollständiges kartesisches Produkt aus jeder Version, Fähigkeit, jedem Kanal und jeder Einstellung der Zugangsinformation wächst so lange, bis es niemand mehr ausführt. Halte eine kleine Pflichtmatrix vor, die jede Sicherheitsentscheidung abdeckt, und füge einen Fall hinzu, sobald ein neuer Adapterzweig erscheint.

Verwende die Form der Initialisierung als Zeilen und den lokalen Entscheidungsstatus als Spalten. Führe beispielsweise einen Client mit der ältesten unterstützten Version, einen Client mit leeren Fähigkeiten und einen normalen aktuellen Client gegen einen gesperrten Tresor, eine nicht freigegebene Sitzung, eine sitzungsfreigegebene Zugangsinformation und eine Zugangsinformation mit Prüfung pro Aufruf aus. Führe jede relevante Zelle über HTTP und SSH aus, wenn beide Kanäle denselben Autorisierungspfad verwenden, aber unterschiedliche Ausführungshelfer nutzen.

Das erwartete Ergebnis sollte vor dem Test in klaren Worten festgehalten werden:

ClientbedingungLokaler ZustandErwartetes Ergebnis
Älteste akzeptierte VersionTresor gesperrtAktion abgelehnt und protokolliert
Leere FähigkeitenTresor entsperrt, neuer ProzessSitzungsfreigabe angefordert und protokolliert
Ältere VersionFreigegebener Prozess, Schlüssel mit Prüfung pro AufrufPrüfung pro Aufruf für jede Aktion angefordert
Nicht unterstützte VersionBeliebiger ZustandInitialisierung abgelehnt, keine ausgehende Aktion
Aktuelle VersionProzess widerrufenAktion abgelehnt und protokolliert

Diese Tabelle verdient ihren Platz, weil sie eine Entscheidung über nicht unterstützte Versionen erzwingt. Lass den Server nach einer fehlgeschlagenen Verhandlung nicht „sein Bestes versuchen“. Diese Formulierung bedeutet oft, dass er eine Anfrage auf einem Parserpfad ausführt, der deutlich weniger getestet wurde als der unterstützte Pfad. Lehne die Sitzung ab, protokolliere die Ablehnung sicher und verlange einen unterstützten Client.

Sammle für jede Zeile drei unabhängige Beobachtungen: die rohe MCP-Antwort, eine Beobachtung beim simulierten HTTP-Dienst oder Test-SSH-Host und das Auditergebnis. Eine Fehlerantwort allein kann nicht beweisen, dass keine Aktion die Außenwelt erreicht hat. Ein Testendpunkt allein kann nicht beweisen, dass das Gateway die Ablehnung aufgezeichnet hat. Du brauchst alle drei.

Ein Fehlerprotokoll sollte die verletzte Grenze benennen

Wenn ein Kompatibilitätstest fehlschlägt, erfasse ihn nicht als „alter MCP-Client hat Probleme“. Diese Beschreibung sorgt dafür, dass ein anderer Entwickler die Darstellung repariert und die Autorisierung übersieht.

Benenne die Invariante und zeige den Zeitablauf. Das ist ein Fehlerbericht, mit dem man arbeiten kann:

Client B initialized with oldest accepted version and no optional capabilities.
Client A had already received session approval and was still running.
Client B sent an HTTP action using the same displayed clientInfo name.
Gateway injected the credential and the test endpoint received the request.
No approval card appeared for B.
Activity journal recorded completion, but Sessions journal contained only A.

Diese Abfolge zeigt, dass der Fehler bei Prozessidentität oder dem Gültigkeitsbereich des Autorisierungscaches liegt, nicht beim Parsen der Version. Sie zeigt außerdem, ob das Audit-Log einen Eintrag enthält, der einen Ermittler in die Irre führen könnte. Füge den Regressionstest auf dieser Ebene hinzu und verfolge den Fehler anschließend nach innen, bis die Implementierung eine einzige Autorisierungsprüfung besitzt, die B nicht umgehen kann.

Ein zweites Fehlermuster ist subtiler:

Client initialized without the capability used for approval status updates.
Credential required per-call review.
First action displayed local review and completed.
Second action completed immediately.
Audit log recorded two completed actions and one review event.

Das deutet auf ein Prüf-Token hin, das seinen Aktionsbereich verlassen hat. Die Lösung besteht nicht darin, den alten Client zu verbieten. Die Freigabeprüfung muss an eine Aktions-Nonce oder einen internen Aktionsdatensatz gebunden, genau einmal verwendet und danach verbraucht werden.

Diese Transkripte helfen Supportteams auch dabei, eine Benutzerentscheidung von einem Softwarefehler zu unterscheiden. Wenn das Journal zeigt, dass ein Benutzer eine Prüfung abgelehnt hat, untersuche die Anfrage. Wenn dort steht, dass für eine Zugangsinformation mit erforderlicher Prüfung keine Prüfung stattgefunden hat, darfst du das Ereignis nicht länger als normales Agentenverhalten behandeln.

Sperren und Widerruf sind getrennte Tests

Die Freigabe folgt dem Prozess
Neue Agent-Prozesse brauchen eine lokale Sitzungsfreigabe, unabhängig von Protokollversion oder angegebenen Fähigkeiten.

Tresortor, Sitzungsfreigabe und Prüfung pro Aufruf beantworten unterschiedliche Fragen. Eine Downgrade-Suite sollte sie getrennt testen, weil ein bestandener Freigabetest einen Fehler beim Sperren des Tresors verbergen kann und umgekehrt.

Sperre zuerst den Tresor. Starte jedes Kompatibilitäts-Fixture, einschließlich der ältesten akzeptierten Version. Jede geschützte Aktion muss vor dem Einschleusen von Zugangsdaten und bevor der externe Dienst irgendetwas sieht fehlschlagen. Akzeptiere kein Ergebnis, das den Agenten lediglich auffordert, selbst Zugangsdaten bereitzustellen. Der Agent darf sie niemals erhalten.

Entsperre anschließend den Tresor, lasse die Sitzung aber nicht freigegeben. Das Fixture sollte für seinen Lauf genau einen Pfad zur Sitzungsautorisierung erhalten. Gib ihn frei, führe eine geschützte Aktion aus und widerrufe danach die Sitzung, während der Prozess weiterläuft. Die nächste Aktion muss fehlschlagen, obwohl der Tresor entsperrt bleibt.

Verwende schließlich eine Zugangsinformation mit Prüfung pro Aufruf in dieser freigegebenen Sitzung. Gib eine Aktion frei, lehne die nächste ab und prüfe das Journal. Diese Abfolge beweist, dass die Entscheidungskette ihre Reihenfolge beibehält: Der Tresor blockiert jede Aktion im gesperrten Zustand. Die Sitzungsfreigabe begründet die Berechtigung dieses Prozesses. Die Einstellung der Zugangsinformation kann darüber hinaus eine neue Entscheidung verlangen.

Fasse diese Tests nicht zu einem einzigen langen Szenario zusammen, ohne zusätzlich fokussierte Tests für jede Grenze beizubehalten. Lange End-to-End-Tests zeigen gut, dass ein Weg existiert. Sie zeigen schlecht, warum er nach einer Überarbeitung kaputtgegangen ist.

Release-Gates müssen stillen Erfolg bestrafen

Kompatibilitätsfehler sollten eine Veröffentlichung blockieren, wenn sie eine Aktion unbemerkt ermöglichen. Eine kleine Abweichung in einer Statusmeldung kann im nächsten Patch behoben werden. Ein herabgestufter Client, der eine Freigabe übernimmt, die Prüfung pro Aufruf überspringt, bei gesperrtem Tresor handelt oder aus der Audit-Spur verschwindet, hat eine Sicherheitsgrenze überschritten.

Mache diese Tests in der Continuous Integration für jede Änderung verpflichtend, die MCP-Initialisierung, Protokolladapter, Zustellung von Freigaben, Prozessverfolgung, Einschleusen von Zugangsdaten oder Audit-Projektion betrifft. Warte nicht auf eine neue Protokollversion. Das Risiko entsteht durch Verzweigungen rund um eine fehlende Fähigkeit, und normale Feature-Arbeit erzeugt solche Zweige ständig.

Der Test, der sich meist sofort bezahlt macht, ist der unschöne: eine alte Clientdeklaration, ein leeres Fähigkeitsobjekt, ein wiederverwendeter Anzeigename, ein zweiter Prozess und eine zweite Verwendung der Zugangsinformation, nachdem die erste freigegeben wurde. Behalte ihn bei. So findest du den freundlichen Kompatibilitätscode, der eine menschliche Entscheidung still in einen Cache-Treffer verwandelt hat.

FAQ

Wie viele ältere MCP-Protokollversionen sollte ich testen?

Teste die Version, deren Unterstützung du weiterhin zusicherst, sowie die älteste Version, die dein Kompatibilitätscode versehentlich akzeptieren könnte. Teste außerdem einen Client, der eine aktuelle Version angibt, aber optionale Felder für Fähigkeiten weglässt. Dieser zweite Fall findet Parser- und Standardwertfehler, die ein normaler Test mit einem alten Client nicht entdeckt.

Kann eine MCP-Client-Fähigkeit eine Freigabeaufforderung entfernen?

Nein. Die Fähigkeitserklärung eines Clients beschreibt, was er kann oder anzeigen kann. Sie entscheidet nicht darüber, ob das Aktions-Gateway die Identität prüft, eine Überprüfung verlangt oder eine Aktion protokolliert.

Was soll passieren, wenn ein MCP-Client fehlerhafte Fähigkeiten sendet?

Lehne fehlerhafte Initialisierungsnachrichten sauber ab. Verweigere anschließend geschützte Aktionen, bis die Sitzung eine gültige Initialisierung und einen gültigen Autorisierungsweg durchlaufen hat. Rate nicht, was ein fehlerhafter Client beabsichtigt hat. Ein großzügiger Parser ist eine als Kompatibilität getarnte Autorisierungsentscheidung.

Wie teste ich, dass eine Sitzungsfreigabe nicht wiederverwendet werden kann?

Wenn die Freigabe an eine Sitzung gebunden ist, verknüpfe sie mit dem tatsächlichen Client-Prozess oder einer ähnlich starken Laufzeitidentität, nicht mit einer vom Aufrufer gelieferten Sitzungsbezeichnung. Ein neuer Prozess muss seine eigene Freigabe erhalten, auch wenn er denselben Clientnamen verwendet und dieselben Tools anfordert.

Sollte eine Prüfung pro Aufruf mit einem Client funktionieren, der keine Benachrichtigungen unterstützt?

Die Prüfung gehört zur sensiblen Aktion und zur Richtlinie der Zugangsdaten, nicht zu einer vom Client angekündigten Benachrichtigungsfunktion. Wenn der Client keine normale interaktive Prüfung anzeigen kann, sollte das Gateway seinen lokalen Prüfpfad verwenden oder die Aktion ablehnen. Ein stiller Fallback ist die unsichere Wahl.

Warum müssen herabgestufte Clients weiterhin Audit-Einträge erzeugen?

Weil eine fähigkeitsabhängige Protokollierung genau dann eine Lücke erzeugt, wenn der Kompatibilitätscode einen ungewöhnlichen Weg nimmt. Erfasse Versuch, Autorisierungsergebnis, Zielidentität und Ergebnis über denselben Audit-Pfad wie bei aktuellen Clients.

Was beweist eine Offline-Prüfung der Audit-Kette?

Sie beweist, dass die verschlüsselte Hash-Kette nicht verändert oder unterbrochen wurde. Sie beweist jedoch nicht, dass jedes erwartete Testereignis aufgezeichnet wurde. Kombiniere die Prüfung mit Aussagen, die das Vorhandensein der erwarteten Ereignisse sowie die richtigen Felder für Autorisierung und Ergebnis kontrollieren.

Brauchen MCP-Downgrade-Tests eine End-to-End-Abdeckung?

Ja, sofern das Testsystem als echter Client-Prozess agieren und die lokalen Freigabe- und Audit-Oberflächen prüfen kann. Unit-Tests finden Parser-Regressionen, beweisen aber selten, dass Prozessidentität, menschliche Entscheidung, Ausführung und Protokollierung verbunden geblieben sind.

Ist eine fehlende MCP-Fähigkeit automatisch ein Sicherheitsproblem?

Nein. Fehlende optionale Fähigkeiten dürfen nur den Komfort verringern. Sie dürfen niemals aus einem geschützten Aufruf einen ungeprüften Aufruf machen, den Eintrag eines Versuchs löschen oder die Berechtigung nach dem Beenden des Clients weiterlaufen lassen.

Welche Fehler in Downgrade-Tests sollten eine Veröffentlichung blockieren?

Ein Fehler blockiert die Veröffentlichung, wenn ein älterer oder unvollständiger Client mit Zugangsdaten nach einer fehlenden Freigabe ausführen, eine Prüfung pro Aufruf umgehen, die Sitzungsautorisierung eines anderen Prozesses übernehmen oder keinen manipulationssicheren Audit-Eintrag erzeugen kann. Kosmetische Unterschiede bei der Darstellung können warten. Diese Fehler dürfen es nicht.

Sallyport

Sallyport führt API-Aufrufe und SSH-Befehle für Ihren KI-Agenten aus. Die Schlüssel bleiben in einem lokalen Tresor auf Ihrem Mac; Sie geben jeden Lauf frei, und jede Aktion landet in einem versiegelten Journal.

© 2026 Sallyport · Open Source unter Apache-2.0 · Oleg Sotnikov