CVE-2026-63469 — fastapi-code-generator
Fix: koxudaxi/fastapi-code-generator@49301dbCVE-2026-63469 is a Code Injection vulnerability in fastapi-code-generator. A fix is available for fastapi-code-generator — see the affected versions and patch details below.
fastapi-code-generator: Import-time RCE via response status-code key -> unescaped @app.get(..., responses={...}) dict
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
- CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
- A successful exploit gives an attacker total control of the affected component, not partial access.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-63469.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
Real-World Exposure
fastapi-code-generatorReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.
Description
Summary
fastapi-code-generator (koxudaxi) emits an operation's extra responses into the route decorator's responses={...} dict, using each response's status-code key as a single-quoted string literal without escaping the '. A ' in a status-code key closes the dict-key string and, via concatenation, injects a live expression that the decorator argument evaluates when main.py is imported (the ASGI server imports it at startup) -- code execution, no request. The status-code key is a pure data field. Verified on fastapi-code-generator 0.8.0 / Python 3 / FastAPI.
Details
@app.get(
'/u', response_model=None,
responses={
'404' + (__import__("os").system('…') or "") + 'x': {'model': Thing}
},
)
def get_thing() -> None:
pass
The responses={...} dict is emitted only when the operation has a second (non-primary) response, so the malicious key is any additional response status. The generator post-processes with black/isort, so a syntax-breaking payload aborts generation (DoS); a valid-Python concat ('+expr+', kept valid with (... or "")) is written and runs at import. The response content-type key is NOT a sink (normalized to 'model'). info.* are repr-escaped; operationId -> function_name fails closed (DoS-resistant).
Not a duplicate: same product as the path -> @app.get('…') and summary -> handler-docstring findings, but a different field (response status-code key) and position (the responses={...} decorator dict key). Distinct from OpenAPI Generator's python-fastapi. Models come from datamodel-code-generator (repr-escaped).
PoC
reproduce.sh (+ make_spec.py) attached: generates the app and merely imports main.py; the injected expression runs at decorator evaluation and writes a marker. Verified on 0.8.0.
Impact
Code execution at import/startup in any application/CI that generates a FastAPI app with
fastapi-code-generator from an attacker-controlled or attacker-influenced spec (multi-response operation)
and imports/serves it. Estimated Critical, e.g. CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N.
Suggested fix
Escape each response status-code key for the Python string literal (escape ', , newlines via repr) before emitting the responses={...} dict, and validate that status-code keys are numeric / a known pattern. maintainer-report.txt make_spec.py reproduce.sh
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐍PyPI | fastapi-code-generator | all versions | 0.8.1pip install --upgrade 'fastapi-code-generator==0.8.1' |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for fastapi-code-generator, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update fastapi-code-generator to 0.8.1 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-63469 is resolved across your whole dependency graph.
Workarounds
Stop passing untrusted input into the interpreter or shell: call the affected binary with an argument array rather than a composed command string, reject anything outside a strict allowlist of expected values, and run the component under an account that cannot reach beyond the work it legitimately does.
Frequently Asked Questions
Is CVE-2026-63469 in your dependencies?
Find it across PyPI, including transitive dependencies.