GitHub Advisoryadvisory · crates.io
GHSA-4hgp-59h5-gvrj ratex-parser panics on `\verb` with a multibyte delimiter (UTF-8 byte-boundary slice)
HIGH
Official page ↗
- Aliases
- CVE-2026-53530
- Ecosystem
- crates.io
- Packages
- ratex-parser
- Severity
- High
- CVSS vector
- CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
- Weaknesses
- CWE-1285, CWE-248, CWE-400
- Reviewed
- 2026-07-07
Affected packages
• crates.io ratex-parser: < 0.1.11 → fixed in 0.1.11
Description
Summary
The public parser entrypoint `ratex_parser::parse(&str)` panics on the 9-byte input `\verbéxé` (i.e. `\verb` followed by the non-ASCII delimiter `é`). When handling a `\verb` command, the parser slices the verbatim argument with byte indices (`arg[1..arg.len() - 1]`); if the delimiter character is multibyte UTF-8, index `1` lands inside that character and Rust panics with *“byte index 1 is not a char boundary”*. Because RaTeX’s release profile sets `panic = "abort"` (`Cargo.toml:48`), the panic aborts the entire process — not just the current request/thread — making this a hard denial of service for any service that renders untrusted LaTeX.
Details
Affected code
`crates/ratex-parser/src/parser.rs`, `parse_symbol_inner`:
```rust
if let Some(stripped) = text.strip_prefix("\\verb") { // parser.rs:901
self.consume();
let arg = stripped.to_string(); // e.g. "éxé"
let star = arg.starts_with('*');
let arg = if star { &arg[1..] } else { &arg }; // parser.rs:905 (also byte-sliced)
if arg.len() …` correctly with char semantics (`lexer.rs` `lex_verb`); only the parser mishandles it.
PoC
```
$ printf '\\verb\xc3\xa9x\xc3\xa9\n' | ./target/release/parse
thread 'main' panicked at crates/ratex-parser/src/parser.rs:910:27:
start byte index 1 is not a char boundary; it is inside 'é' (bytes 0..2 of string)
Aborted (core dumped) # exit 134 — panic=abort kills the whole process
```
Impact
Any application that renders untrusted LaTeX through RaTeX (web “render this math” endpoint, WASM in-browser use, the FFI embedded in another app) can be crashed by a tiny string. With `panic = "abort"` in release builds, the crash takes down the whole process / server, so a single malicious formula causes a full-service DoS (and, in batch pipelines, drops all queued work).
Remediation
Slice by character boundaries instead of byte indices, mirroring the UTF-8-correct logic the lexer already uses. For example:
```rust
let chars: Vec = arg.chars().collect();
if chars.len() < 2 { return Err(ParseError::new("\\verb assertion failed", Some(&nucleus))); }
let body: String = chars[1..chars.len() - 1].iter().collect();
```
(Apply the same char-aware handling to the `*` strip at `parser.rs:905`.) More broadly, consider not using `panic = "abort"` for builds embedded in long-running services, and/or wrapping parsing in `catch_unwind` at the FFI/WASM boundary — but the byte-slice fix is the direct correction.
Related
Alias · CVE (1)
- CVE-2026-53530 RaTeX is a KaTeX-compatible math rendering engine written in Rust. vulnerability