internals: Escape control chars in parse errors
What changed, and why it matters
This commit fixes a log-injection-style issue in error messages. When the library failed to parse a string, it would print the user's raw input directly into the error text. If that input contained hidden control characters such as newlines or tabs, those characters would appear in logs or other output, potentially confusing log parsers, hiding malicious content, or making errors harder to read. The fix escapes those characters so they appear as visible symbols instead of being executed as formatting.
Treat as a low-severity hardening fix. Review other Display/Debug implementations in the crate for similar verbatim rendering of untrusted input, and consider adding regression tests that feed control-character strings into parse errors to verify escaping.
Security signals we found
Control characters rendered verbatim in error output
Log/output injection risk from attacker-controlled input
Use of escape_debug to sanitize untrusted string content
Fix located in error Display formatting path
Evidence from the diff
In internals/src/error/input_string.rs, the cannot_parse and unknown_variant Display helpers previously rendered the raw Storage input verbatim via write!(…). The patch changes both to call input.escape_debug() before formatting, which escapes ASCII control characters (e.g., \n, \t, \r) and non-printable Unicode. This prevents attacker-controlled input from injecting control characters into error strings that may be written to logs, terminals, or structured output, mitigating log injection and output-formatting attacks.
Changed components
internals/src/error/input_string.rsInputString error Display implementationcannot_parse helperunknown_variant helperInspect captured patch +2 / −2
### internals/src/error/input_string.rs
@@ -156,14 +156,14 @@ mod storage {
where
W: fmt::Display + ?Sized,
{
- write!(f, "failed to parse '{}' as {}", input, what)
+ write!(f, "failed to parse '{}' as {}", input.escape_debug(), what)
}
pub(super) fn unknown_variant<W>(inp: &Storage, what: &W, f: &mut fmt::Formatter) -> fmt::Result
where
W: fmt::Display + ?Sized,
{
- write!(f, "'{}' is not a known {}", inp, what)
+ write!(f, "'{}' is not a known {}", inp.escape_debug(), what)
}
impl_from!(alloc::string::String, alloc::boxed::Box<str>, alloc::borrow::Cow<'_, str>);Why this scored 49/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.