Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-63720-datamodel-code-generator — Code injection (RCE) in datamodel-code-generator via unvalidated customBasePath (CVE-2026-63720) | Kitploit
Tools/GitHubGitHub/rahulreddykarne/cve-2026-63720-datamodel-code-generator
Vulnerability AnalysisExploitationSupply Chain SecurityLearning & EducationPayload Development
GitHubrahulreddykarne/cve-2026-63720-datamodel-code-generator

CVE-2026-63720-datamodel-code-generator

Code injection (RCE) in datamodel-code-generator via unvalidated customBasePath (CVE-2026-63720)

View Repository
141 month agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-63720: Code Injection in datamodel-code-generator via Unvalidated customBasePath

Severity: High, CVSS 3.1 7.5 / CVSS 4.0 7.5 (assigned by VulnCheck, the CNA)

Environmental ceiling (network-service deployment): up to 9.8

Vector (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

Vector (v3.1): CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H

Affected: datamodel-code-generator < 0.70.0

Fixed in: 0.70.0

CWE: CWE-94 (Improper Control of Generation of Code, 'Code Injection')

Reported by: Rahul Karne

CNA: VulnCheck

Published: July 26, 2026


Summary

datamodel-code-generator validated every schema-controlled import string that could carry a code-injection payload, except one.

The tool converts an input schema (JSON Schema, OpenAPI, YAML) into Python model source. Several schema fields are rendered directly into that generated code, so the project validates them as dotted Python identifiers before use, specifically to prevent injection. The schema extension field customBasePath is the one sibling that skips this check. Its value flows unsanitized into a from ... import ... statement in the generated output. An attacker who controls the input schema can embed arbitrary Python using newlines and a dot-free expression, and it executes the moment the generated module is imported, which is the ordinary next step after generating models.

This is an incomplete fix of CVE-2026-55415 (GHSA-5578-w22f-pfx9), which hardened the sibling fields customTypePath and x-python-import against this exact class. That fix did not cover customBasePath, which reaches the identical sink unvalidated and remained exploitable through 0.68.1 and main until 0.70.0.

Impact

Arbitrary Python code execution in the process that imports or runs the generated models: the developer's machine, a CI runner, or any service that generates and then loads models. Confidentiality, integrity, and availability of the host are fully compromised, bounded only by the privileges of that process.

The severity depends entirely on where codegen runs on untrusted input:

  • Local developer workflow. A developer generates models from a schema they did not author (a fetched or third-party OpenAPI document) and imports the result. Code runs as the developer. This is the assigned-base case.
  • CI / build pipeline. A pipeline generates models from third-party specs and runs tests. Code runs on the CI runner with whatever credentials it holds.
  • Network service (environmental ceiling, up to 9.8). A service that accepts a schema over HTTP, generates models, and loads them, for example a B2B platform that auto-generates SDKs from customer-supplied OpenAPI specs, runs the attacker's code on the server from a single unauthenticated request with no user interaction. This is the deployment the maintainer's own sibling advisory (GHSA-m34r) names as in scope.

Who is affected: Any use of datamodel-code-generator < 0.70.0 that (1) generates models from a schema whose customBasePath value is attacker influenced, and (2) imports or executes the generated module. The default codegen-then-import workflow satisfies (2) inherently.

Who is not affected:

  • Anyone on 0.70.0 or later, where customBasePath is validated.
  • Workflows that only ever generate models from fully trusted, first-party schemas.
  • Workflows that generate source but never import or execute it (rare, since generating models to use them is the point of the tool).

Reach

MetricValueSource
Downloads, all-time194 Millionpepy.tech/projects/datamodel-code-generator
Downloads, last 30 days16.3 Millionpepy.tech
Typical deploymentDeveloper machines, CI/CD pipelines, and SDK-generation platforms that codegen from OpenAPI / JSON Schemainherent to the tool's function

Technical detail

Root cause

The value of the customBasePath schema field is carried into generated code with no identifier constraint. Three points in the codebase matter (paths relative to src/datamodel_code_generator/):

  • Schema entry point. parser/jsonschema.py defines the field custom_base_path with alias="customBasePath" (~line 644), consumed via _resolve_base_class(...) at several call sites.
  • Missing validation. parser/base.py, _resolve_base_class (~line 1665), returns the value after only a local normalize() (dedup/strip). No identifier validation is applied.
  • Sink. imports.py, Import.from_full_path() (~line 35), emits the value verbatim as a from ... import ... line. The value is also used as the class base in model/base.py set_base_class (~line 1324) and rendered raw by the model template (class {{ class_name }}({{ base_class }}):).

Because the value is written into Python source with no constraint, embedded newlines and a dot-free expression survive into the output as their own individually parseable lines, and the middle line executes on import.

The payload is dot-free by necessity. Import.from_full_path splits the value on ., so a normal os.system(...) call would be broken apart. Using getattr(__import__('os'),'system')(...) avoids any . while still resolving the same call, and the surrounding newlines keep the emitted from ... import ... lines syntactically valid so the injected middle line runs cleanly.

Why this survived a hardened codebase

This is not a project that neglected injection. The maintainer hardened this exact class repeatedly across multiple advisories (GHSA-5578, m34r, 8m8r, wjv6), each time routing a schema-controlled import or type string through _validate_dotted_python_identifier_path before it reaches code generation. The sibling fields customTypePath (validated at parser/jsonschema.py ~lines 4956, 5202) and x-python-import (~line 2096) both go through that validator.

customBasePath is the one sibling with no such call. It reaches the same Import.from_full_path sink by a different path (_resolve_base_class) that was never wired into the validation the other fields received. The defect survived precisely because the surrounding defense looked complete: a reviewer scanning for unvalidated import strings sees validators on the fields they check first, and this one routes through a helper that looks like base-class resolution rather than import handling. It is a gap in a systematic fix, not an absent one, which is why it persisted into the latest release.

Exploitation preconditions

An attacker needs:

  1. A target using datamodel-code-generator < 0.70.0.
  2. Control over the customBasePath value in a schema the target will process, in practice by supplying or influencing the input schema (a third-party OpenAPI/JSON Schema document, or a schema submitted to a service).
  3. The target to import or run the generated module, which is the normal codegen-then-use workflow.

No authentication or elevated privileges are required of the attacker (PR:N). The base score reflects that the victim performs the ordinary generate-and-import action (UI:R in v3.1 / UI:A in v4.0); the network-service deployment removes even that, which is where the environmental 9.8 comes from.

Proof of concept

The following was run against the real, unmodified package. Reproduction:

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"

Attacker 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" } }
}

Generated generated_models.py on the vulnerable version (0.68.1):

Download Tool