-
-
Notifications
You must be signed in to change notification settings - Fork 172
Description
Submitted by email from @zefr0x
When using anyhow::Result in the main function, user input can be printed unintentionally via an error's core::fmt::Display implementation when the application exits, it might print ANSI escape sequences, potentially compromising the integrity of log files and interacting with terminal emulators.
Terminals vary in supporting ANSI codes, but modern ones usually allow arbitrary changes to the terminal display including hiding logs or writing fake ones, writing clickable hyperlinks, changing the terminal title, inserting content to the system clipboard, and sending desktop notifications etc...
By itself, it might lead to presenting falsified information in logs and allow clickbaiting attacks. However, due to the huge attack surface, accompanied with another vulnerability or misconfiguration in the terminal, system clipboard, or applications reading the clipboard etc... it might result in an arbitrary code execution.
You can search "Weaponizing ANSI Escape Sequences" for more details and examples.
Similar CVEs
- CVE-2020-7694
- CVE-2023-4571
- CVE-2024-52005
- CVE-2024-27936
- CVE-2025-30089
Possible solutions
-
Always use the
Debugtrait when printing error messages, as it will escape error messages from possible malicious non-visible characters by default usingstd::char::escape_debug. -
Always use
std::char::escape_defaulton output string before printing it.
PoC
[package]
name = "poc"
version = "0.1.0"
edition = "2024"
[dependencies]
anyhow = "1.0"#[derive(Debug)]
struct MyCustomError {
details: String,
}
impl std::error::Error for MyCustomError {}
impl core::fmt::Display for MyCustomError {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "MyCustomError: {}", self.details)
}
}
fn validate_id(id: &str) -> Result<(), MyCustomError> {
if id.contains("123") {
Ok(())
} else {
Err(MyCustomError {
details: String::from(format!("`{id}` is missing `123`")),
})
}
}
fn main() -> anyhow::Result<()> {
let user_input = "\x1b]0;Changed Terminal Window Title\x07 \x1b[1J\x1b[4m\x1b[1;34mtest";
validate_id(user_input)?;
Ok(())
}