Eigene Forschung
CVE-2026-104776: Dateilesen über kubectl_patch in mcp-server-kubernetes erklärt
CVE-2026-104776 ist eine Schwachstelle im Open-Source-Projekt mcp-server-kubernetes: Das Werkzeug kubectl_patch nahm über den Parameter patchFile einen Dateipfad an und ließ kubectl diese Datei auf dem Server lesen, auch wenn der Server über einen Netzwerk-Transport betrieben wurde. Die vier Geschwister-Werkzeuge mit vergleichbarem Pfad-Parameter lehnten genau das bereits ab, kubectl_patch fehlte diese Prüfung. Die GitHub-Advisory bewertet die Lücke mit CVSS 7.1 (hoch), betroffen sind alle Versionen bis einschließlich 4.1.0, behoben ist sie in 4.1.1, gemeldet von CyberSec42.
- Über
patchFilekonnte ein Aufrufer einen Pfad auf dem Server-Host angeben, etwa zu einer Kubeconfig oder einem Service-Account-Token. Inhalte konnten über Fehlermeldungen oder über einen anschließend lesbaren Patch zum Aufrufer zurückfließen. - Betroffen war nur der Betrieb über SSE oder Streamable HTTP. Im Standardmodus stdio ist der Aufrufer der Betreiber selbst, dort ändert der Fix nichts.
- Bewertung laut Advisory: CVSS 3.1 Basiswert 7.1, Vektor
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N, Klasse CWE-73. - Was Betreiber tun sollten: auf 4.1.1 oder neuer aktualisieren. Lief ein Netzwerk-Transport für nicht vollständig vertrauenswürdige Aufrufer, empfehlen wir zusätzlich, die auf dem Server liegenden Zugangsdaten zu erneuern.
Hintergrund
Was der Server macht und welche Betriebsarten er kennt.
Zum AbschnittDie Schwachstelle
Mechanik in einfachen Worten und technisch.
Zum AbschnittWer betroffen war
Versionen und Betriebsarten.
Zum AbschnittBehebung
Was der Fix ändert und was Betreiber tun sollten.
Zum AbschnittZeitleiste
Nur öffentlich belegte Daten.
Zum AbschnittDas Muster dahinter
Wenn einem Werkzeug die Prüfung seiner Geschwister fehlt.
Zum AbschnittDie Fakten auf einen Blick
| Merkmal | Angabe |
|---|---|
| Kennung | CVE-2026-104776 (zugeteilt), GHSA-6963-p4fp-2wxw |
| Produkt | mcp-server-kubernetes (npm, Repository Flux159/mcp-server-kubernetes) |
| Klasse | Serverseitiges Lesen beliebiger Dateien; CWE-73 „External Control of File Name or Path“ |
| Schwere | CVSS 3.1: 7.1, hoch (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N) |
| Betroffen | alle Versionen bis einschließlich 4.1.0, nur bei Betrieb über SSE oder Streamable HTTP |
| Behoben | 4.1.1, veröffentlicht am 27.07.2026 |
| Veröffentlicht | GitHub-Advisory am 02.10.2026; der CVE-Eintrag bei MITRE war am 28.10.2026 noch nicht veröffentlicht |
| Credit | Gemeldet von CyberSec42 (GitHub: lwebmedia) |
Hintergrund: Was mcp-server-kubernetes ist
Das Model Context Protocol (MCP) ist ein offener Standard, über den KI-Assistenten Werkzeuge ansprechen. mcp-server-kubernetes ist ein quelloffener MCP-Server unter MIT-Lizenz, der laut Repository Befehle zur Verwaltung von Kubernetes bereitstellt. Er übersetzt Werkzeugaufrufe eines KI-Clients in Aufrufe von kubectl und helm, etwa kubectl_get, kubectl_apply oder kubectl_patch. Dabei handelt der Server mit den Kubernetes-Zugangsdaten, die auf seinem Host hinterlegt sind.
Für diesen Fall entscheidend ist die Betriebsart, im MCP-Jargon der Transport. Standard ist stdio: Der KI-Client startet den Server als lokalen Prozess, Aufrufer und Betreiber sind dieselbe Person auf demselben Rechner. Optional lässt sich der Server über die Umgebungsvariablen ENABLE_UNSAFE_SSE_TRANSPORT oder ENABLE_UNSAFE_STREAMABLE_HTTP_TRANSPORT als Netzwerkdienst starten. Die erweiterte Dokumentation des Projekts beschreibt beide Wege samt Docker-Beispiel und empfiehlt für den Produktivbetrieb zusätzlich eine Header-Authentifizierung über MCP_AUTH_TOKEN.
Im Netzwerkbetrieb gilt ein Grundsatz, den das Projekt selbst im Quellcode festhält: Ein Dateipfad, den ein Aufrufer übergibt, wird auf dem Server-Host aufgelöst, nicht beim Aufrufer. Deshalb hatten die Maintainer im Juli 2026 in zwei Pull Requests (#332 und #346) Pfad-Parameter für Netzwerk-Transporte gesperrt, und zwar bei kubectl_create, kubectl_apply, kubectl_delete sowie bei Installation und Upgrade von Helm-Charts. Grundsätzliches zur Absicherung solcher Server steht in unserem Leitfaden zu MCP-Servern; hier geht es um den konkreten Fall.
Wie wir geprüft haben
Der Befund stammt aus einer reinen Quellcode-Prüfung des öffentlichen Repositorys. Laut Advisory wurde dabei weder eine fremde Installation von mcp-server-kubernetes noch ein Kubernetes-Cluster, eine Kubeconfig oder ein anderes fremdes System angesprochen, gescannt oder ausgenutzt. Das abweichende Verhalten haben wir ausschließlich auf dem eigenen Rechner gegen den kompilierten Code nachgestellt, ohne Netzwerkanfrage und ohne Cluster. Die Meldung lief vertraulich über die private Schwachstellenmeldung des Repositorys auf GitHub.
Die Schwachstelle
In einfachen Worten
Stellen Sie sich ein Büro vor, in dem Besucher Formulare einreichen. Für vier Formulartypen gilt die Regel: Besucher von außen dürfen nicht auf „das Dokument im Schrank, Fach 3“ verweisen, sie müssen ihre Unterlagen selbst mitbringen. Beim fünften Formulartyp fehlte diese Regel. Ein Besucher konnte dort auf ein Fach im Schrank verweisen, und der Sachbearbeiter holte das Dokument heraus und arbeitete damit. Passte es nicht ins Formular, las er in seiner Rückmeldung Teile davon vor.
So verhielt sich kubectl_patch bis Version 4.1.0. Der Schrank ist das Dateisystem des Servers, das Fach ist der Parameter patchFile.
Technisch
Das Werkzeug kubectl_patch akzeptiert die Änderung entweder direkt als Daten (patchData) oder als Pfad zu einer Datei (patchFile). Den Pfad reichte es als --patch-file an kubectl weiter, das auf dem Server-Host mit dessen Rechten läuft. Die Geschwister-Werkzeuge prüfen vor genau diesem Schritt mit der Funktion isRemoteTransport(), ob der Server über das Netzwerk betrieben wird, und lehnen den Pfad dann ab. In kubectl-patch.ts fehlte dieser Aufruf. Eine zweite, allgemeine Schutzschicht des Projekts prüft zwar alle Argumente für kubectl, laut Advisory aber nur die Namen bestimmter Optionen, nicht den Wert dahinter. Für den Pfad bot sie deshalb keinen Schutz.
Wie Inhalte zurückfließen konnten, beschreibt die Advisory in zwei Varianten. Ist die Datei kein gültiges JSON oder YAML, scheitert kubectl beim Einlesen, und die Fehlermeldung samt Kontext aus der Datei wurde unverändert in der Antwort an den Aufrufer zurückgegeben. Ist die Datei gültig, was bei vielen Konfigurations- und Zugangsdateien naheliegt, wird ihr Inhalt als Patch auf eine Kubernetes-Ressource angewendet. Diese Ressource kann der Aufrufer anschließend über kubectl_get vollständig lesen.
Zur Einordnung des Vektors: PR:L bedeutet, dass ein Aufrufer niedrige Berechtigungen braucht, hier einen gültigen Wert für den Header X-MCP-AUTH, wenn der Betreiber MCP_AUTH_TOKEN gesetzt hat. C:H steht für den Verlust der Vertraulichkeit, I:L für die begrenzte Integritätsauswirkung des ungewollten Patches. Wir haben den Basiswert von 7.1 anhand der Formel der CVSS-Spezifikation nachgerechnet. Die Advisory weist selbst darauf hin, dass der Wert ohne gesetzten Token höher läge, rund 8.2, und dass ein Betreiber mit offenem Netzwerk-Transport ohne Token ohnehin allen erreichbaren Aufrufern weitreichende Cluster-Werkzeuge zugänglich macht. Beide Werte liegen im Band „hoch“, gemeldet wurde der niedrigere.
Schematischer Ablauf
- Der Betreiber startet
mcp-server-kubernetesmit SSE oder Streamable HTTP. Auf dem Host liegen Kubernetes-Zugangsdaten. - Ein Aufrufer, der den Endpunkt erreicht und gegebenenfalls den Auth-Header kennt, ruft
kubectl_patchmit einem Pfad auf dem Server-Host alspatchFileauf. - Der Server prüft den Transport nicht und übergibt den Pfad an
kubectl, das die Datei mit den Rechten des Servers öffnet. - Ist die Datei kein gültiger Patch, enthält die zurückgegebene Fehlermeldung Kontext aus der Datei. Ist sie gültig, landet ihr Inhalt in einer Ressource, die über
kubectl_getlesbar ist.
Wir veröffentlichen bewusst keinen Exploit-Code und keine Beispielanfrage. Die Beschreibung reicht, um die eigene Installation einzuordnen und den Fix nachzuvollziehen.
Wer betroffen war
Die Advisory nennt das npm-Paket mcp-server-kubernetes in allen Versionen bis einschließlich 4.1.0. Im Quellcode von 4.1.0 fehlt der Aufruf von isRemoteTransport() in kubectl-patch.ts, ab 4.1.1 ist er vorhanden. Ob ein Server über das Netzwerk betrieben wird, entscheidet die Funktion allein anhand der beiden Umgebungsvariablen für SSE und Streamable HTTP.
| Betriebsart | Einordnung bis 4.1.0 |
|---|---|
stdio (Standard, lokaler Prozess) | Nicht betroffen. Der Aufrufer ist der Betreiber auf seinem eigenen Rechner, der Fix ändert dieses Verhalten nicht |
SSE oder Streamable HTTP, MCP_AUTH_TOKEN gesetzt | Betroffen für jeden, der den Endpunkt erreicht und einen gültigen Auth-Header besitzt |
SSE oder Streamable HTTP, kein MCP_AUTH_TOKEN | Betroffen für jeden, der den Endpunkt erreicht |
Mit ALLOW_ONLY_READONLY_TOOLS=true | Laut Advisory nicht erreichbar, weil kubectl_patch nicht zu den freigegebenen Werkzeugen gehört. ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS=true schließt das Werkzeug dagegen nicht aus |
Wie groß das Risiko im Einzelfall war, hängt davon ab, wer den Endpunkt erreichen konnte, und davon, welche Dateien auf dem Server-Host lagen. Die Advisory nennt als typische Ziele eine eingebundene Kubeconfig, den Token des Service-Accounts eines Pods und die Umgebungsvariablen des Prozesses.
Behebung und was Betreiber jetzt tun sollten
Was der Fix in 4.1.1 ändert
Pull Request #355 überträgt die bestehende Regel auf kubectl_patch: Läuft der Server über SSE oder Streamable HTTP, wird patchFile mit einer Fehlermeldung abgelehnt, die auf patchData verweist. Die Beschreibung des Parameters im Werkzeugschema nennt die Einschränkung jetzt ausdrücklich, wie bei den Geschwister-Werkzeugen. Das Verhalten im stdio-Modus bleibt unverändert. Außerdem ergänzt der Fix die bestehende Testdatei für Pfad-Parameter bei Netzwerk-Transporten um kubectl_patch, für beide Transport-Variablen.
Gerade der Test ist der nachhaltige Teil: Er schließt die Lücke in der Testabdeckung, durch die kubectl_patch von seinen Geschwistern abweichen konnte.
Empfehlungen für Betreiber
Die folgenden Schritte sind unsere Empfehlungen, keine Vorgaben der Maintainer.
| Schritt | Maßnahme |
|---|---|
| 1. Version prüfen | Auf 4.1.1 oder neuer aktualisieren. Die Advisory führt 4.1.1 als erste behobene Version. |
| 2. Betriebsart klären | Prüfen, ob ENABLE_UNSAFE_SSE_TRANSPORT oder ENABLE_UNSAFE_STREAMABLE_HTTP_TRANSPORT gesetzt war. Wenn nicht, bestand der beschriebene Weg nicht. |
| 3. Zugangsdaten erneuern | Lief ein Netzwerk-Transport, der für nicht vollständig vertrauenswürdige Aufrufer erreichbar war: Kubeconfig-Zugangsdaten und Service-Account-Token erneuern sowie Geheimnisse aus den Umgebungsvariablen des Prozesses austauschen. |
| 4. Endpunkt abschirmen | MCP_AUTH_TOKEN setzen, den Endpunkt nicht ungeschützt ins Netz stellen und TLS vorschalten, wie es die Projektdokumentation für den Produktivbetrieb empfiehlt. |
| 5. Werkzeuge begrenzen | Nur die Werkzeuge freigeben, die wirklich gebraucht werden, etwa über ALLOW_ONLY_READONLY_TOOLS oder ALLOWED_TOOLS. |
| 6. Rechte begrenzen | Dem Server nur die Cluster-Rechte geben, die die freigegebenen Werkzeuge brauchen, und keine fremden Geheimnisse auf seinem Host ablegen. |
Zeitleiste
Aufgeführt sind nur Daten, die sich aus öffentlichen Quellen belegen lassen.
| Datum | Ereignis | Beleg |
|---|---|---|
| 13.07.2026 | Pull Request #332: Pfad-Parameter von kubectl_create bei Netzwerk-Transport gesperrt | GitHub-Commit |
| 18.07.2026 | Pull Request #346: dieselbe Regel für kubectl_apply, kubectl_delete und Helm | GitHub-Commit |
| 26.07.2026 | Release 4.1.0, die letzte betroffene Version | GitHub-Release, npm |
| 27.07.2026 | Quellcode-Prüfung auf Stand von 4.1.0, laut Advisory | GitHub-Advisory |
| 27.07.2026 | Fix gemergt (Pull Request #355), Release 4.1.1 | GitHub, npm |
| 02.10.2026 | GHSA-6963-p4fp-2wxw mit CVE-2026-104776 veröffentlicht | GitHub-Advisory |
| 28.10.2026 | CVE-Eintrag bei MITRE noch nicht veröffentlicht | Abfrage der CVE-Services-Schnittstelle |
Die korrigierte Version stand damit mehr als zwei Monate vor der öffentlichen Beschreibung der Schwachstelle bereit.
Das Muster dahinter: Wenn einem Werkzeug die Prüfung seiner Geschwister fehlt
CVE-2026-104776 ist kein neuer Fehlertyp. Die Maintainer hatten die Gefahr erkannt, benannt und an vier Stellen behoben. Die Lücke lag in der fünften Stelle, die beim Nachziehen übersehen wurde. Wir nennen das Geschwister-Asymmetrie: Mehrere Werkzeuge haben dieselbe Form von Eingabe, aber nur ein Teil von ihnen prüft sie. Solche Fälle sind in MCP-Servern naheliegend, weil jedes Werkzeug eine eigene Datei mit eigener Eingabeverarbeitung ist und Schutzregeln oft pro Werkzeug eingebaut werden.
In unserer Erläuterung der OWASP MCP Top 10 berührt der Fall vor allem Klasse 10 (unsicherer Dateizugriff) und Klasse 7 (Zugangsdaten, die abfließen können). Dazu kommt ein Aspekt aus Klasse 4: Eine Schutzschicht, die alle Argumente sieht, aber nur Optionsnamen prüft, kann den Eindruck vollständiger Absicherung erwecken. Für Entwickler von MCP-Servern lassen sich daraus vier Regeln ableiten:
- Regeln zentral durchsetzen. Eine Prüfung wie „keine Server-Pfade bei Netzwerk-Transport“ gehört an eine Stelle, die alle Werkzeuge durchlaufen, nicht in jedes Werkzeug einzeln. Die Advisory schlägt genau diese strukturelle Lösung vor.
- Beim Nachziehen alle Geschwister suchen. Wer eine Schutzregel auf weitere Werkzeuge ausweitet, sucht nach der Form der Eingabe, also nach jedem Parameter, der einen Pfad annimmt, nicht nach bekannten Werkzeugnamen.
- Den Negativfall für jedes Werkzeug testen. Ein Test, der für jedes Werkzeug mit Pfad-Parameter die Ablehnung prüft, macht Abweichungen sofort sichtbar.
- Fehlermeldungen nicht ungefiltert zurückgeben. Rohe Fehlerausgaben externer Programme können Inhalte enthalten, die nicht für den Aufrufer bestimmt sind.
Für Betreiber gilt die Kehrseite: Ein MCP-Server mit Netzwerk-Transport ist ein Netzwerkdienst mit Zugriff auf Ihren Cluster und auf das Dateisystem seines Hosts. Er verdient dieselbe Behandlung wie jede andere API mit Geheimnissen, also Authentifizierung, minimale Rechte und eine bewusst kleine Werkzeugliste. Weitere öffentlich dokumentierte Funde finden Sie auf unserer Seite Forschung.
Dank an die Maintainer
Wir danken den Maintainern von mcp-server-kubernetes für die koordinierte Zusammenarbeit. Die Meldung lief vertraulich über die private Schwachstellenmeldung von GitHub. Die Maintainer haben den Fix mit Tests umgesetzt, die korrigierte Version lange vor der Veröffentlichung bereitgestellt und die Advisory mit CVE-Nummer und Nennung von CyberSec42 veröffentlicht. Bemerkenswert ist, wie nachvollziehbar das Projekt seine Sicherheitsentscheidungen dokumentiert: Die Begründung der Pfad-Sperre steht als Kommentar direkt im Code und in den Beschreibungen der Pull Requests.
Prüfen alle Werkzeuge Ihres MCP-Servers dasselbe?
Wir prüfen MCP-Server und KI-Agenten im schriftlich vereinbarten Umfang: ob Schutzregeln für alle Werkzeuge gleich gelten, welche Dateien und Zugangsdaten ein Werkzeugaufruf erreichen kann, wie die Transporte abgesichert sind und was ein Aufrufer tatsächlich bewirken kann. Jeder Befund kommt mit einem nachvollziehbaren Nachweis und einem konkreten Korrekturvorschlag. Mehr dazu unter KI-Pentest & MCP-Sicherheit.
KI-Pentest anfragenCyberSec42 ist eine unabhängige technische Sicherheitsprüfung, keine akkreditierte Zertifizierungsstelle und keine Rechtsberatung. CyberSec42 steht in keiner Verbindung zu den Maintainern von mcp-server-kubernetes.
Häufige Fragen
Was ist CVE-2026-104776?
Eine Schwachstelle im MCP-Server mcp-server-kubernetes. Das Werkzeug kubectl_patch ließ über den Parameter patchFile Dateien auf dem Server-Host lesen, auch bei Betrieb über das Netzwerk, wo die Geschwister-Werkzeuge solche Pfade bereits ablehnten. Die GitHub-Advisory bewertet sie mit CVSS 7.1 (hoch).
Welche Versionen sind betroffen?
Laut Advisory alle Versionen bis einschließlich 4.1.0. Behoben ist die Schwachstelle in 4.1.1 vom 27.07.2026. Aktualisieren Sie auf 4.1.1 oder neuer.
Bin ich betroffen, wenn ich den Server über stdio nutze?
Nein. Die Prüfung greift nur, wenn der Server über SSE oder Streamable HTTP läuft. Im stdio-Modus ist der Aufrufer der Betreiber auf seinem eigenen Rechner, der Fix ändert dort nichts. Aktualisieren sollten Sie trotzdem, weil sich die Betriebsart später ändern kann.
Warum gibt es noch keinen Eintrag auf cve.org?
Die CVE-Nummer ist zugeteilt und in der GitHub-Advisory vermerkt. Der zugehörige Eintrag bei MITRE war bei unserer Abfrage am 28.10.2026 noch nicht veröffentlicht. Maßgeblich für Versionen und Bewertung ist bis dahin die GitHub-Advisory.
Wurde die Schwachstelle aktiv ausgenutzt?
Darüber treffen die öffentlichen Quellen keine Aussage. Unsere Prüfung war eine reine Quellcode-Analyse, bei der kein fremdes System angesprochen wurde.
Weiterlesen
- Forschung: unsere öffentlich dokumentierten Funde
- CVE-2026-15583: SSRF im Grafana MCP Server erklärt
- Die OWASP MCP Top 10, praktisch erklärt
- MCP-Server absichern: der praktische Leitfaden
- Leistung: KI-Pentest & MCP-Sicherheit
Quellen
- GitHub-Advisory: GHSA-6963-p4fp-2wxw (CVE-2026-104776)
- GitHub: mcp-server-kubernetes Pull Request #355
- GitHub: Änderungen zwischen v4.1.0 und v4.1.1
- GitHub: mcp-server-kubernetes Release v4.1.1
- GitHub: Pull Request #332 und Pull Request #346
- GitHub: ADVANCED_README.md (Transporte und Authentifizierung)
- npm: mcp-server-kubernetes
- MITRE: CWE-73
- FIRST: CVSS v3.1 Specification
- Model Context Protocol: Transports