par_term/paste_transform/sanitize.rs
1//! Paste content sanitization: strips dangerous terminal control characters.
2
3/// Check whether a paste string contains dangerous control characters that would
4/// be stripped by [`sanitize_paste_content`].
5///
6/// Returns `true` if the input contains any of:
7/// - C0 control characters (0x00-0x1F) other than Tab, Newline, Carriage Return
8/// - ESC (0x1B)
9/// - DEL (0x7F)
10/// - C1 control characters (0x80-0x9F) including CSI (0x9B)
11///
12/// Used to generate a warning log entry when `warn_paste_control_chars` is enabled.
13pub fn paste_contains_control_chars(input: &str) -> bool {
14 input.chars().any(|ch| {
15 let code = ch as u32;
16 if ch == '\t' || ch == '\n' || ch == '\r' {
17 return false;
18 }
19 if code <= 0x1F {
20 return true;
21 }
22 if code == 0x7F {
23 return true;
24 }
25 (0x80..=0x9F).contains(&code)
26 })
27}
28
29/// Sanitize clipboard paste content by stripping dangerous control characters.
30///
31/// Removes characters that could inject terminal escape sequences when pasted:
32/// - C0 control characters (0x00-0x1F) **except** Tab (0x09), Newline (0x0A),
33/// and Carriage Return (0x0D) which are safe/expected in paste content
34/// - ESC (0x1B) is explicitly stripped to prevent escape sequence injection
35/// - C1 control characters (0x80-0x9F) including CSI (0x9B)
36///
37/// All normal printable ASCII, extended Latin, and Unicode text passes through
38/// unchanged.
39pub fn sanitize_paste_content(input: &str) -> String {
40 input
41 .chars()
42 .filter(|&ch| {
43 let code = ch as u32;
44 // Allow safe C0 controls: Tab, Newline, Carriage Return
45 if ch == '\t' || ch == '\n' || ch == '\r' {
46 return true;
47 }
48 // Strip C0 control characters (0x00-0x1F) — includes ESC (0x1B)
49 if code <= 0x1F {
50 return false;
51 }
52 // Strip DEL (0x7F)
53 if code == 0x7F {
54 return false;
55 }
56 // Strip C1 control characters (0x80-0x9F) — includes CSI (0x9B)
57 if (0x80..=0x9F).contains(&code) {
58 return false;
59 }
60 true
61 })
62 .collect()
63}