TROVE-2026-024: Malicious directory cache can crash arti clients
### Meta Reported by 5225225, see arti!4049. Assigned TROVE-2026-024 for it. Keeping this confidential for now but I think we can open it up, given that it is a zero day. ### Synopsis a44d2e1c600b710b7a669dce96b37108302318a0 introduced changes to an already not-so-nice parser for `PortPolicy`. The code can be found below: ```rust /// Very bad parser for [`PortPolicy`], please use `parse2`! fn from_str(s: &str) -> Result<Self, Self::Err> { // TODO: The error is bad but kept for backwards compatibility. // Also, we should do split_whitespace but I feel doing this is not // worth it anymore; introduces an unnecessary risk of adding // bugs. if s.len() < 7 { // We need to do this because RuleKind::from_str does not check for // the space between "accept/reject" and the arguments. return Err(PolicyError::InvalidPort); } let kind = RuleKind::from_str(&s[..6]).map_err(|_| PolicyError::InvalidPort)?; let s = &s[7..]; let mut allowed = PortRanges::from_str(s)?; if kind == RuleKind::Reject { allowed.invert(); } Ok(Self { allowed }) } ``` The problem here are the following lines: ``` let kind = RuleKind::from_str(&s[..6]).map_err(|_| PolicyError::InvalidPort)?; let s = &s[7..]; ``` This will crash in the case if it rips up a UTF-8 code point, as per [`SliceIndex<str>`](https://doc.rust-lang.org/std/primitive.str.html#impl-SliceIndex%3Cstr%3E-for-(Bound%3Cusize%3E,+Bound%3Cusize%3E)) > Panics if begin or end (if it exists and once adjusted for inclusion/exclusion) does not point to the starting byte offset of a character (as defined by is_char_boundary), if begin > end, or if end > len. A potential example of this is the following input: `acce ¬`, as it contains a two byte UTF-8 point at `5..=6`, which gets cut off by `&s[0..6]`. ### Solutions Use `.split()` or something similar to safely split the string. ### Impact Unfortunately, `tor-dirmgr` only verifies the digest provided by a secure and trusted dirauth **after** parsing it, meaning that a malicious directory mirror can provide an invalid microdesc that will lead arti to crash before noticing the checksum violation. I think we should backport this. I assigned `TROVE-2026-024` and severity `Medium` for it because it can denial someones service but no privacy leaks are involved, making `High` unjustified. cc @nickm @Diziet
issue