## https://sploitus.com/exploit?id=F49E101F-7F33-59F4-80EA-0E437F9BE8CA
# CVE-2026-47103: Python StateMachine Remote Code Execution via SCXML eval() Injection
**Severity:** Critical, CVSS 4.0 **9.3**, CVSS 3.1 **9.8** (assigned by VulnCheck, the CNA)
**Vector (v4.0):** `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`
**Vector (v3.1):** `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H`
**Affected:** Python StateMachine `>= 3.0.0, `. In vulnerable versions, those expression strings pass through the SCXML datamodel processing path and eventually reach Python's built-in `eval()` without sandboxing.
An attacker who can supply or influence an SCXML document can place Python code inside a `` attribute. When the consuming application parses the SCXML file and starts the processor, the expression is evaluated in the context of the hosting Python process.
## Impact
An attacker may execute arbitrary Python code if a vulnerable application processes attacker-controlled SCXML content.
The exposure can be remote or local depending on how the consuming application receives SCXML documents. Risky input paths include:
- Uploaded SCXML files.
- User-controlled workflow or state-machine definitions.
- Configuration files loaded from untrusted locations.
- Plugin, extension, or integration-provided SCXML content.
- Any network-facing feature that accepts or generates SCXML from user input.
Successful exploitation can allow:
- Reading or modifying files accessible to the hosting process.
- Accessing environment variables and application secrets.
- Calling internal services reachable from the host.
- Disrupting or replacing application behavior.
## Affected Path
The vulnerable call chain reported to VulnCheck is:
```text
SCXMLProcessor.parse_scxml_file()
SCXMLProcessor.process_definition()
create_datamodel_action_callable()
_create_dataitem_callable()
_eval()
eval()
```
The issue is triggered when a parsed SCXML datamodel item is evaluated during processor startup.
## Technical Detail
The vulnerable control flow has two trust-boundary failures:
1. The SCXML processor accepts expression text from an SCXML document.
2. The expression text is evaluated with raw Python `eval()`.
The PoC uses a `` attribute because this path executes during `SCXMLProcessor.start()`. Passing an empty globals dictionary to `eval()` does not disable Python builtins; Python can still inject usable builtins into the evaluation context. As a result, an expression can access `__import__` and execute Python code.
A harmless proof payload writes a local marker file:
```xml
```
The marker is created only after the SCXML document is parsed and `start()` evaluates the datamodel expression.
## Proof of Concept
[`package_builder.py`](./package_builder.py) generates a local attacker-controlled SCXML file at `malicious-charts/data_expr_start.scxml`. The generated file contains a benign `` payload that writes `marker.txt` in this PoC directory.
[`run_poc.py`](./run_poc.py) installs no hooks and does not modify the target package. It imports the published `python-statemachine==3.1.2` package, parses the generated SCXML file with `SCXMLProcessor.parse_scxml_file(...)`, starts the processor, and prints before/after marker evidence.
Run in a local test environment only:
```bash
python -m venv .venv
.venv\Scripts\activate
python -m pip install -r requirements.txt
python run_poc.py
```
Expected evidence on vulnerable versions:
```text
statemachine_version: 3.1.2
installed_package: True
data_marker_before_start: False
data_marker_after_start: True
marker_contents:
python_statemachine_scxml_data_expr_eval_triggered
success: True
```
The important behavior is that `marker.txt` does not exist before `start()`, then exists afterward, proving that the SCXML expression executed inside the hosting Python process.
The payload is intentionally harmless. It only writes this local marker string:
```text
python_statemachine_scxml_data_expr_eval_triggered
```
It does not spawn a shell, connect to a network service, read secrets, delete data, or modify files outside the PoC directory.
## Remediation
Upgrade to Python StateMachine `3.2.0` or later.
A durable fix should avoid evaluating attacker-controlled SCXML expression text with raw Python `eval()`. Safer approaches include:
- Replacing raw `eval()` with a constrained expression evaluator.
- Treating full Python expression evaluation as an explicit trusted-input mode.
- Disabling Python evaluation by default for SCXML from untrusted sources.
- Rejecting or sanitizing dangerous SCXML expression attributes before processing.
If immediate upgrade is not possible:
- Do not process SCXML documents from untrusted users.
- Do not expose SCXML upload or workflow-definition features to unauthenticated clients.
- Validate SCXML files before they reach `SCXMLProcessor`.
- Run SCXML processing in a restricted, isolated environment with minimal privileges.
## Disclosure Timeline
| Date | Event |
|---|---|
| May 22, 2026 | Vulnerability submitted to VulnCheck |
| May 26, 2026 | VulnCheck initiated disclosure; `CVE-2026-47103` provisionally allocated |
| June 16, 2026 | `CVE-2026-47103` published |
| June 17, 2026 | CNA record updated by VulnCheck |
## Credit
Discovered and reported by **Sai Teja Erukude**, coordinated through VulnCheck.
## References
- CVE Record: https://vulners.com/cve/CVE-2026-47103
- NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-47103
- VulnCheck advisory: https://www.vulncheck.com/advisories/python-statemachine-rce-via-scxml-eval-injection
- GitHub advisory: https://github.com/fgmacedo/python-statemachine/security/advisories/GHSA-v4jc-pm6r-3vj8
- Python StateMachine 3.2.0 release notes: https://github.com/fgmacedo/python-statemachine/releases/tag/v3.2.0
- Python StateMachine project: https://github.com/fgmacedo/python-statemachine