GitHub Advisoryadvisory · crates.io

GHSA-4hgp-59h5-gvrj ratex-parser panics on `\verb` with a multibyte delimiter (UTF-8 byte-boundary slice)

HIGH Published 2026-07-07 Modified 2026-07-07 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

Weakness · CWE (3)

  • CWE-1285 Improper Validation of Specified Index, Position, or Offset in Input weakness
  • CWE-248 Uncaught Exception weakness
  • CWE-400 Uncontrolled Resource Consumption weakness

References