Sploitus

Exploit for Code Injection in Fgmacedo Python Statemachine

githubexploit Β· 2026-08-15

Exploit Code

README140 lines
## 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