KIberschutz: Vier Lücken in c4, dann das Archiv
Wir meldeten codecentrics c4 GenAI Suite vier hohe Funde. Alle sind behoben und ausgeliefert. Kurz danach ging das Projekt ins Archiv.
Transparenz vorweg: KIberschutz ist unser eigenes Projekt. Wir prüfen mit KI-Unterstützung Open-Source-Software auf Sicherheitslücken und melden die Funde verantwortungsvoll an die Maintainer. Nach logtide, Speakr, Mira, itflow und hopp ist das der sechste Fall.
Es ist auch der erste, bei dem uns die Zeit ein wenig davongelaufen ist. Vier Funde mit hoher Schwere sind behoben, ausgeliefert und seit dem 28. August als öffentliche Advisories dokumentiert. Wenige Tage später hat codecentric das Repository archiviert. Es ist damit schreibgeschützt, und was jetzt noch offen ist, bleibt offen.
Um welche Software es geht
Die c4 GenAI Suite ist eine Chat- und Assistenten-Plattform für Unternehmen, entwickelt von codecentric. Administratoren bauen darin Assistenten zusammen und rüsten sie über Erweiterungen mit Fähigkeiten aus, etwa mit RAG über eigene Dokumente oder mit angebundenen MCP-Servern. Nutzer stellen Fragen, laden eigene Dateien hoch und arbeiten mit den Antworten weiter. Das Backend ist NestJS, das Frontend React, der RAG-Dienst läuft als Python-FastAPI-Service daneben. Apache-2.0, 174 Sterne auf GitHub.
Genau dieses Nutzungsmuster macht die Plattform für uns interessant. In so einem System liegen die internen Fragen einer Firma, hochgeladene Dokumente und die Antworten darauf. Wer Zugriff auf fremde Unterhaltungen bekommt, liest nicht Metadaten, sondern Inhalte. Und weil solche Suiten typischerweise selbst gehostet und an das eigene Identitätssystem gehängt werden, ist die Anmeldung die Grenze, die alles andere trägt.
Der Scan lief am 24. Juli über das Backend, 77.456 Zeilen in 1.086 Dateien. Die Funde daraus haben wir am 27. Juli als private Advisories eingereicht. Vier davon sind heute öffentlich, und um die geht es hier.
Die vier veröffentlichten Funde
| Fund | Schwere | Kurz erklärt |
|---|---|---|
| Kontoübernahme über die GitHub-Anmeldung | hoch | Bei aktiver GitHub-Anmeldung nahm die Software den frei wählbaren Anzeigenamen als E-Mail-Adresse. Wer seinen Anzeigenamen auf die Adresse eines Opfers setzte, landete in dessen Konto, auch in einem Administratorkonto |
| SQL-Injection im Suchfeld | hoch | Die Suche in der Datei- und Nutzerliste baute ihre Datenbankabfrage per Textverkettung zusammen. Ein einzelnes Anführungszeichen im Suchbegriff genügte, um aus der Suche auszubrechen. Die Dateisuche stand jedem angemeldeten Nutzer offen |
| Server holt beliebige URLs ab | hoch | Ein Endpunkt zur Bucket-Konfiguration nahm eine mitgeschickte Adresse und rief sie serverseitig ab, ohne die Administratorprüfung, die seine Nachbarendpunkte hatten. Damit ließen sich interne Dienste anklopfen. Zusätzlich war die TLS-Prüfung für diese Anfragen abgeschaltet |
| Fremde Unterhaltungen lesbar | hoch | Das Duplizieren einer Unterhaltung suchte sie nur über ihre Nummer, ohne zu prüfen, wem sie gehört. Jeder angemeldete Nutzer konnte fremde Unterhaltungen samt Nachrichten kopieren und damit lesen. Die Nummern sind schlicht durchgezählt |
Der letzte Fund ist der, den wir für eine Chat-Plattform am unangenehmsten finden. Er klingt nach einer Kleinigkeit, weil "duplizieren" nach einer Komfortfunktion klingt. Praktisch ist es eine Leseberechtigung: Wer eine fremde Unterhaltung kopiert, hat danach deren kompletten Verlauf im eigenen Konto. In einer Suite, in der Abteilungen ihre internen Fragen stellen und Dokumente hochladen, ist das der Inhalt selbst.
Ein Tippfehler auf Typebene
Der Fund zur GitHub-Anmeldung ist der lehrreichste, deshalb hier etwas genauer.
Die Anmeldung über GitHub las das Profil des Nutzers aus und nahm daraus die E-Mail-Adresse. Nur liefert die verwendete Bibliothek gar kein einzelnes E-Mail-Feld, sondern eine Liste. Der Code fragte trotzdem nach dem einzelnen Feld und hatte für den Fall, dass es fehlt, einen Rückfall auf den Anzeigenamen eingebaut. Weil das Feld immer fehlte, griff immer der Rückfall. Die Software hat also nie eine E-Mail-Adresse gelesen, sondern immer den Anzeigenamen.
Möglich wurde das durch eine lokale Typdeklaration, die ein Feld versprach, das zur Laufzeit nie existierte. Der Compiler war damit zufrieden, weil er nur die Deklaration sah und nicht das echte Objekt. Die Anmeldung über Microsoft im selben Projekt machte es an der gleichen Stelle richtig und las aus der Liste.
Dazu kam der zweite Teil: Die Anmeldung suchte den passenden Nutzer allein über die E-Mail-Adresse, ohne zu unterscheiden, von welchem Anbieter sie stammt. Beides zusammen ergibt den Angriff. Der Anzeigename ist ein Feld, das jeder in seinem GitHub-Profil in zehn Sekunden ändern kann. Man trägt dort die Adresse der Zielperson ein, meldet sich an, und die Software ordnet einen dem bestehenden Konto zu.
Für sich genommen ist jeder der beiden Bausteine ein kleiner Schludrigkeitsfehler. Zusammen sind sie eine Kontoübernahme bis hinauf zum Administrator. Das ist das Muster, das wir in fast jedem Fall wiederfinden: Nicht die spektakuläre Lücke richtet den Schaden an, sondern zwei harmlose Annahmen, die nie nebeneinander gelegt wurden.
Was bei uns schiefging
Ein Teil dieses Falls geht auf unsere Kappe, und der gehört hierher.
Am 14. August, als wir nach 18 Tagen Stille nachfragten, haben wir uns die eingereichten Advisories noch einmal selbst angesehen. Bei jedem einzelnen war das Feld "Affected products" leer, also weder Paketname noch betroffener Versionsbereich. Beim Einreichen verlangt das Formular die Angabe nicht, fürs Veröffentlichen ist sie dagegen Pflicht. Wir haben sie nachgetragen.
Das ist kein Drama, und wir wollen es auch nicht zu einem machen. Ein Maintainer kann das Feld selbst ausfüllen, es steht im Bearbeiten-Formular direkt unter der Beschreibung, und niemand kennt die betroffenen Versionsbereiche besser als er. Blockiert war also nichts.
Trotzdem gehört es hierher, weil es die Richtung der Arbeit verkehrt. Wer eine Lücke meldet, bittet jemanden um Zeit, den er nicht bezahlt. Da sollte der Report fertig ankommen und keine Hausaufgabe enthalten, die der Empfänger noch erledigen muss, bevor er überhaupt anfangen kann. Wir prüfen die Pflichtfelder deshalb jetzt vor dem Absenden statt Wochen später, und wer selbst Advisories einreicht, sollte an derselben Stelle nachsehen.
Woran die Stille lag, wissen wir nicht, und wir schreiben sie ausdrücklich nicht diesem Feld zu. Am selben Tag, an dem wir nachfragten, kam der erste Fix, und danach ging es zügig.
Die Fixes und ihr blinder Fleck
Die Korrekturen sitzen genau an den gemeldeten Stellen. Die GitHub-Anmeldung liest jetzt aus der E-Mail-Liste statt aus dem Anzeigenamen. Die Suche arbeitet mit Datenbank-Parametern statt mit zusammengebautem Text. Der Bucket-Endpunkt bekam die Administratorprüfung, die seine Nachbarn schon hatten. Und das Duplizieren einer Unterhaltung sucht sie jetzt zusätzlich über den Besitzer.
Am 20. August erschien v10.0.1, wenige Stunden später v10.0.2. Die Advisories nennen 10.0.2 als gepatchte Version und alles bis einschließlich 10.0.0 als betroffen.
Eine Sache fällt dabei auf, und sie ist nicht c4-spezifisch. In den Release Notes zu v10.0.1 steht ein einziger Eintrag, und der betrifft eine Performance-Verbesserung im Frontend. Von den vier Sicherheitsfixes taucht dort keiner auf. Das liegt an dem Weg, den GitHub für private Advisories vorsieht: Der Fix entsteht in einem temporären privaten Fork, damit die Lücke bis zum Release unsichtbar bleibt. Genau deshalb landen diese Commits aber nicht in den automatisch erzeugten Release Notes.
Für Betreiber heißt das: Die Release Notes eines Projekts sind kein verlässlicher Indikator dafür, ob ein Update sicherheitsrelevant ist. Die veröffentlichten Advisories sind es. Bei c4 sind sie seit dem 28. August da, und damit greifen auch die üblichen Abhängigkeits-Scanner. Dass das Team sie selbst veröffentlicht hat, ist der Teil, den viele Projekte auslassen. Wir haben ihn zuletzt bei hopp vermisst.
Und dann kam das Archiv
Nach dem Release vom 20. August kamen nur noch automatische Abhängigkeits-Updates herein, die letzten davon am 31. August. Kurz darauf hat codecentric das Repository archiviert. Es ist seitdem schreibgeschützt, die Projektbeschreibung auf GitHub trägt jetzt den Zusatz "archived". Eine ausführliche Ankündigung dazu haben wir nicht gefunden, weder im README noch in den Release Notes.
Für die vier Funde in diesem Artikel ändert das nichts, die sind behoben und ausgeliefert. Für alles andere ändert es eine Menge. Ein archiviertes Repository nimmt keine Pull Requests mehr an, und der private Meldeweg für Sicherheitslücken ist damit praktisch beendet. Was jetzt noch offen ist, wird nicht mehr geschlossen.
Das ist kein Vorwurf. Projekte werden eingestellt, das ist normal und ehrlicher, als eine tote Codebasis mit einem Wartungsversprechen weiterzuführen. Die vier Advisories vorher noch zu veröffentlichen, war die richtige Reihenfolge, und sie ist keine Selbstverständlichkeit.
Aber es verschiebt die Verantwortung. Wer die c4 GenAI Suite im Haus betreibt, betreibt ab jetzt eine Software ohne Herausgeber. Jede weitere Lücke, egal ob im eigenen Code oder in einer der Abhängigkeiten, muss die eigene Mannschaft finden und fixen.
Was ihr tun solltet
Wenn ihr die c4 GenAI Suite selbst betreibt, ist das hier die kurze Fassung.
Aktualisiert zuerst auf v10.0.2. Alle vier beschriebenen Lücken sind dort behoben, das nennen die Advisories so, und ältere Versionen bis einschließlich 10.0.0 enthalten sie sämtlich.
Prüft danach, ob die Anmeldung über GitHub bei euch aktiv ist oder es einmal war. Der Angriff auf die Konten hinterlässt keine auffälligen Spuren, weil er wie eine normale Anmeldung aussieht. Wer die GitHub-Anmeldung längere Zeit auf einer Version bis 10.0.0 laufen hatte, sollte die Administratorkonten und ihre letzten Anmeldungen einmal durchsehen.
Und dann trefft eine Entscheidung über den weiteren Betrieb, statt sie zu vertagen. Ein archiviertes Projekt heißt nicht, dass ihr die Software morgen abschalten müsst. Es heißt, dass ihr euch bewusst dafür entscheiden solltet, sie weiterzubetreiben, und dann auch den Aufwand einplant: einen eigenen Fork, jemanden, der die Abhängigkeiten im Blick behält, und eine Vorstellung davon, wohin ihr wechselt, wenn das zu teuer wird. Ein Blick in eure Netzwerkregeln lohnt sich bei der Gelegenheit auch. Eine Plattform, die von sich aus Adressen abruft, sollte nicht frei ins interne Netz telefonieren dürfen.
Wie es weitergeht
Der Fall steht auf unserer Statusseite unter dem Klarnamen, weil vier Funde behoben, ausgeliefert und öffentlich dokumentiert sind. Er steht dort aber weiter als offen: Aus demselben Lauf sind noch Funde in Bearbeitung, und solange die es sind, nennen wir dazu keine Details. Das ist die Regel, an die wir uns halten, und das Archiv ändert daran nichts.
Wir schauen uns an, welche Wege es für die verbliebenen Meldungen noch gibt, wenn das Repository keine mehr anbietet. Sobald sich daran etwas tut, steht es hier.
Quellen9
- c4 GenAI Suite v10.0.2 (die von den Advisories genannte gepatchte Version)github.com
- Release Notes zu v10.0.1 (ohne Sicherheitseintrag)github.com
- GHSA-j9fw-jvpw-px52: Kontoübernahme über GitHub-SSOgithub.com
- GHSA-868f-6j87-482r: SQL-Injection im Suchfiltergithub.com
- GHSA-rwqq-9f3p-vq3g: SSRF über den Bucket-Endpunktgithub.com
- GHSA-j6qq-934p-gqhr: fremde Unterhaltungen lesbargithub.com
- Issue #2019: unsere Bitte um einen privaten Meldeweggithub.com
- c4 GenAI Suite auf GitHubgithub.com
- KIberschutz: Status aller Fällekiberblick.de