If you discover a security vulnerability in scxml, please do not open a
public GitHub issue. Instead, email security@gnomes.ch with:
- A description of the issue and its potential impact.
- Steps to reproduce, ideally with a minimal SCXML payload.
- The crate version, Rust version, and target platform.
- Whether you are willing to be credited in the public advisory.
We will acknowledge receipt within 48 hours and aim to provide a fix or mitigation timeline within 7 days. Once a fix is published, we will credit reporters in the release notes unless they prefer to remain anonymous.
Security fixes are provided for the latest published minor version of the crate. Older versions are not patched. Users are encouraged to track the current release.
The crate is designed to safely parse SCXML from untrusted sources via the
parse_untrusted()
entry point. Threats actively mitigated:
| Threat | Mitigation |
|---|---|
| XXE / billion laughs | quick-xml does not expand entities. parse_untrusted rejects <!DOCTYPE and <!ENTITY outright. |
| Memory exhaustion (oversized input) | Configurable max_input_bytes, max_states, max_transitions limits. |
| Stack overflow (deep nesting) | Configurable max_depth (default 20). |
| Identifier injection | All identifiers validated against [a-zA-Z0-9_\-\.:]. |
| Export injection | XML attribute escaping, DOT string escaping, Mermaid sanitisation. |
| Code execution | The Statechart model is inert data. Guards are string names, never evaluated. <script> and <invoke> are stored as descriptors, never executed. #![forbid(unsafe_code)] is enforced. |
The full security model is documented in the README.
The following are not considered vulnerabilities in this crate:
- Misuse of
parse_xml()(the unchecked parser) on untrusted input; useparse_untrusted()instead. - Bugs in downstream consumers of the model (e.g. a calling application that evaluates a guard string as JavaScript).
- Denial of service from a caller setting deliberately permissive
InputLimits. - Issues in Graphviz, Mermaid, or other tools that consume our exporter output.