Sploitus

Exploit for CVE-2026-63720

githubexploit · 2026-08-03

Exploit Code

README195 lines
## https://sploitus.com/exploit?id=83BD58E5-DC6B-56F8-8814-63D976256444
# 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 ` Pull the download figures from pepy.tech before publishing, the same way the
> PyAthena numbers were verified. For a code-generation tool, the deployment
> context (it routinely runs inside CI and SDK-generation services) is as
> important to the reach story as the raw download count, because that is where
> the environmental 9.8 case lives.

## 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 ` RCE_PROOF.txt')\nfrom builtins.object",
  "properties": { "name": { "type": "string" } }
}
```

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

```python
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
```

The attacker's call is emitted verbatim into the generated source.

**On import:** the command executes. In the verified run, the injected marker
printed to stdout and `RCE_PROOF.txt` was created containing the current user
(`root`), confirming arbitrary command execution through the ordinary
generate-and-import workflow.

**On the patched version (0.70.0):** the same schema is rejected before any code
is generated:

```
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"
```

No file is produced. The rejection message names the fix directly: the value is
now required to be a dotted Python identifier path.

**Network-service variant.** An unauthenticated loopback HTTP service that
accepts a POSTed schema, generates models, and imports them was demonstrated
executing the attacker's command on the server from a single unauthenticated
`curl`, with no user interaction. This is the deployment shape behind the
environmental 9.8. The service and attack files are included in the PoC
repository.

## Remediation

Upgrade to datamodel-code-generator `0.70.0` or later:

```
pip install --upgrade "datamodel-code-generator>=0.70.0"
```

`0.70.0` routes `customBasePath` through the same dotted-identifier validation
already applied to `customTypePath` and `x-python-import`, so a value that is not
a valid identifier path is rejected before code generation.

**If you cannot upgrade immediately:** do not generate models from schemas you do
not fully control, and do not import or execute modules generated from untrusted
schemas. There is no configuration flag that adds the missing validation in
affected versions; upgrading is the reliable fix.

**Note for anyone reusing the generator's internals.** The defect was a missing
validation call on one code path into `Import.from_full_path`, not a flaw in the
sink itself. Any downstream project that renders schema-controlled strings into
generated code should validate every such field as a dotted identifier, not only
the ones that pass through the obvious import-handling path.

## On the CVSS score

VulnCheck (the CNA) assigned **7.5 (High)**, matching the base vector the
maintainer used for the parent advisory CVE-2026-55415, because this is the same
injection class, the same `Import.from_full_path` sink, and the same impact.

- `AV:N`: schemas are commonly obtained over the network (fetched or
  third-party OpenAPI / JSON Schema documents).
- `AC:H`: exploitation depends on the victim generating models from the
  malicious schema and then importing or running the generated code.
- `PR:N` / `UI:R` (v3.1): no attacker privileges; the victim performs the
  ordinary codegen-and-import workflow.
- `C:H` / `I:H` / `A:H`: full arbitrary code execution on the host.

The **environmental ceiling is 9.8**
(`AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H`) and applies specifically to the
network-service deployment, where the generator is exposed to untrusted schemas
and no victim interaction is required. That figure is an environmental note for
that deployment, not the assigned base score. Stating both, and being explicit
about which is which, is the honest framing: the base is 7.5, and it reaches 9.8
only in the exposed-service case.

## Disclosure timeline

| Date | Event |
|---|---|
| [[FILL: date]] | Vulnerability identified |
| [[FILL: date]] | Reported (coordinated disclosure) |
| [[FILL: date]] | Fix committed (`545a96c5`) |
| [[FILL: date]] | Patched version 0.70.0 released |
| July 26, 2026 | CVE-2026-63720 published by VulnCheck |

> Fill the discovery, report, and release dates from your own records to
> complete the timeline.

## Credit

Discovered and reported by **Rahul Karne**, security researcher and IEEE Senior
Member. His research focuses on injection and input-handling flaws in
high-dependency open-source packages, including CVE-2026-65321 (SQL injection in
PyAthena) and the parent-class hardening around this finding.

Contact: rahulreddy.karne@gmail.com · GitHub: [rahulreddykarne](https://github.com/rahulreddykarne)

## References

- NVD (CVE-2026-63720): https://nvd.nist.gov/vuln/detail/CVE-2026-63720
- CVE Record: https://vulners.com/cve/CVE-2026-63720
- VulnCheck advisory: https://www.vulncheck.com/advisories/datamodel-code-generator-code-injection-via-unvalidated-custombasepath-schema-field
- Patch commit `545a96c5`: https://github.com/koxudaxi/datamodel-code-generator/commit/545a96c5
- Parent advisory (incomplete fix): CVE-2026-55415 / GHSA-5578-w22f-pfx9
- Project repository: https://github.com/koxudaxi/datamodel-code-generator
- Download statistics: https://pepy.tech/projects/datamodel-code-generator

---

## Press

Media inquiries: rahulreddy.karne@gmail.com. Full PoC (attacker schema,
network-service demo) and additional technical detail available on request.