agentmux_srv/backend/
host_os.rs1pub const MAX_OS_LEN: usize = 16;
14
15pub fn local_os() -> String {
17 std::env::consts::OS.to_string()
18}
19
20pub fn sanitize_os(raw: &str) -> Option<String> {
24 let ok = !raw.is_empty()
25 && raw.len() <= MAX_OS_LEN
26 && raw
27 .bytes()
28 .all(|b| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'_' || b == b'-');
29 ok.then(|| raw.to_string())
30}
31
32#[cfg(test)]
33mod tests {
34 use super::*;
35
36 #[test]
37 fn the_three_platforms_pass_unchanged() {
38 for os in ["windows", "macos", "linux"] {
39 assert_eq!(sanitize_os(os).as_deref(), Some(os));
40 }
41 }
42
43 #[test]
44 fn anything_that_is_not_a_plain_lowercase_token_is_dropped() {
45 assert_eq!(sanitize_os(""), None);
46 assert_eq!(sanitize_os("Windows"), None);
47 assert_eq!(sanitize_os("win dows"), None);
48 assert_eq!(sanitize_os("<b>linux</b>"), None);
49 assert_eq!(sanitize_os("linux\n"), None);
50 assert_eq!(sanitize_os("../etc"), None);
51 assert_eq!(sanitize_os(&"a".repeat(MAX_OS_LEN + 1)), None);
52 assert_eq!(sanitize_os(&"a".repeat(MAX_OS_LEN)).as_deref(), Some("a".repeat(MAX_OS_LEN).as_str()));
53 }
54
55 #[test]
56 fn this_instance_advertises_a_value_it_would_itself_accept() {
57 assert!(sanitize_os(&local_os()).is_some());
58 }
59}