From baf294c8ecaf0a34d2d575e517936107d58aca57 Mon Sep 17 00:00:00 2001 From: Stefan Ruzitschka <362487+icepuma@users.noreply.github.com> Date: Fri, 27 Feb 2026 12:33:03 +0100 Subject: [PATCH] fix: replace serde_yml with serde_yaml_ng Replace unsound and unmaintained serde_yml (RUSTSEC-2025-0068) with serde_yaml_ng, removing the transitive libyml dependency (GHSA #69). Also fix pre-existing clippy::uninlined_format_args warnings and update check.sh to use --all-features --all-targets. --- Cargo.lock | 32 ++++++++----------- app/Cargo.toml | 2 +- app/src/config/mod.rs | 2 +- check.sh | 2 +- lib/Cargo.toml | 2 +- lib/src/actions/command/run.rs | 4 +-- lib/src/actions/directory/copy.rs | 2 +- lib/src/actions/directory/create.rs | 2 +- lib/src/actions/directory/remove.rs | 2 +- lib/src/actions/file/chown.rs | 4 +-- lib/src/actions/file/copy.rs | 4 +-- lib/src/actions/file/download.rs | 4 +-- lib/src/actions/file/link.rs | 8 ++--- lib/src/actions/file/remove.rs | 2 +- lib/src/actions/file/unarchive.rs | 2 +- lib/src/actions/mod.rs | 6 ++-- lib/src/actions/package/install.rs | 2 +- lib/src/actions/package/providers/aptitude.rs | 4 +-- lib/src/actions/package/providers/mod.rs | 2 +- lib/src/actions/plugin/plugin.rs | 10 +++--- lib/src/atoms/file/unarchive.rs | 3 +- lib/src/contexts/mod.rs | 2 +- lib/src/contexts/privilege.rs | 2 +- lib/src/contexts/variable_include/file.rs | 2 +- lib/src/manifests/load.rs | 2 +- lib/src/tera_functions/mod.rs | 5 ++- lib/src/values/mod.rs | 6 ++-- 27 files changed, 56 insertions(+), 64 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dab95e5b..4042c8ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -636,7 +636,7 @@ dependencies = [ "predicates", "rhai", "serde", - "serde_yml", + "serde_yaml_ng", "strip-ansi-escapes", "tealr", "tempfile", @@ -676,7 +676,7 @@ dependencies = [ "serde", "serde_json", "serde_with", - "serde_yml", + "serde_yaml_ng", "sha256", "tar", "tealr", @@ -3285,16 +3285,6 @@ dependencies = [ "redox_syscall 0.7.2", ] -[[package]] -name = "libyml" -version = "0.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3302702afa434ffa30847a83305f0a69d6abd74293b6554c18ec85c7ef30c980" -dependencies = [ - "anyhow", - "version_check", -] - [[package]] name = "linked-hash-map" version = "0.5.6" @@ -5127,18 +5117,16 @@ dependencies = [ ] [[package]] -name = "serde_yml" -version = "0.0.12" +name = "serde_yaml_ng" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd" +checksum = "7b4db627b98b36d4203a7b458cf3573730f2bb591b28871d916dfa9efabfd41f" dependencies = [ "indexmap 2.13.0", "itoa", - "libyml", - "memchr", "ryu", "serde", - "version_check", + "unsafe-libyaml", ] [[package]] @@ -5469,7 +5457,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.4.1", "once_cell", "rustix 1.1.4", "windows-sys 0.61.2", @@ -6041,6 +6029,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "untrusted" version = "0.9.0" diff --git a/app/Cargo.toml b/app/Cargo.toml index ef4cdd05..6b54c269 100644 --- a/app/Cargo.toml +++ b/app/Cargo.toml @@ -22,7 +22,7 @@ tracing-subscriber = "0.3" update-informer = "1.3" dirs-next = "2.0" serde = { version = "1.0", features = ["derive"] } -serde_yml = "0" +serde_yaml_ng = "0.10" tealr = { version = "0.10.0", features = [ "mlua", "mlua_lua54", diff --git a/app/src/config/mod.rs b/app/src/config/mod.rs index 463b6c4b..fe3d5bb6 100644 --- a/app/src/config/mod.rs +++ b/app/src/config/mod.rs @@ -123,7 +123,7 @@ pub fn lib_config(args: &GlobalArgs) -> anyhow::Result { ..Default::default() }, - false => serde_yml::from_str(yaml.as_str()) + false => serde_yaml_ng::from_str(yaml.as_str()) .with_context(|| "Found Comtrya.yaml, but couldn't deserialize the YAML.")?, }; diff --git a/check.sh b/check.sh index 27ad2c8d..9a754dea 100755 --- a/check.sh +++ b/check.sh @@ -2,5 +2,5 @@ set -euo pipefail cargo fmt -cargo clippy --tests +cargo clippy --all-features --all-targets cargo test diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 45b7a0fb..dac0f08e 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -27,7 +27,7 @@ rhai = { version = "1.24", features = ["serde"] } schemars = "1.2" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -serde_yml = "0" +serde_yaml_ng = "0.10" sha256 = "1.6" tokio = "1.49" toml = "1.0" diff --git a/lib/src/actions/command/run.rs b/lib/src/actions/command/run.rs index f0152153..a707957b 100644 --- a/lib/src/actions/command/run.rs +++ b/lib/src/actions/command/run.rs @@ -77,7 +77,7 @@ mod tests { - hi "#; - let mut actions: Vec = serde_yml::from_str(yaml).unwrap(); + let mut actions: Vec = serde_yaml_ng::from_str(yaml).unwrap(); match actions.pop() { Some(Actions::CommandRun(action)) => { @@ -101,7 +101,7 @@ mod tests { GOROOT: test "#; - let mut actions: Vec = serde_yml::from_str(yaml).unwrap(); + let mut actions: Vec = serde_yaml_ng::from_str(yaml).unwrap(); match actions.pop() { Some(Actions::CommandRun(action)) => { diff --git a/lib/src/actions/directory/copy.rs b/lib/src/actions/directory/copy.rs index f8917c72..714f8d18 100644 --- a/lib/src/actions/directory/copy.rs +++ b/lib/src/actions/directory/copy.rs @@ -92,7 +92,7 @@ mod tests { #[test] fn it_can_be_deserialized() { let example_yaml = std::fs::File::open(get_manifest_dir().join("dircopy.yaml")).unwrap(); - let mut manifest: Manifest = serde_yml::from_reader(example_yaml).unwrap(); + let mut manifest: Manifest = serde_yaml_ng::from_reader(example_yaml).unwrap(); match manifest.actions.pop() { Some(Actions::DirectoryCopy(action)) => { diff --git a/lib/src/actions/directory/create.rs b/lib/src/actions/directory/create.rs index 31489df8..27211f6b 100644 --- a/lib/src/actions/directory/create.rs +++ b/lib/src/actions/directory/create.rs @@ -45,7 +45,7 @@ mod tests { #[test] fn it_can_be_deserialized() { let example_yaml = std::fs::File::open(get_manifest_dir().join("create.yaml")).unwrap(); - let mut manifest: Manifest = serde_yml::from_reader(example_yaml).unwrap(); + let mut manifest: Manifest = serde_yaml_ng::from_reader(example_yaml).unwrap(); match manifest.actions.pop() { Some(Actions::DirectoryCreate(action)) => { diff --git a/lib/src/actions/directory/remove.rs b/lib/src/actions/directory/remove.rs index 1353cd9b..01072437 100644 --- a/lib/src/actions/directory/remove.rs +++ b/lib/src/actions/directory/remove.rs @@ -50,7 +50,7 @@ mod tests { target: a "#; - let mut actions: Vec = serde_yml::from_str(yaml).unwrap(); + let mut actions: Vec = serde_yaml_ng::from_str(yaml).unwrap(); match actions.pop() { Some(Actions::DirectoryRemove(action)) => { diff --git a/lib/src/actions/file/chown.rs b/lib/src/actions/file/chown.rs index e7df0208..5d647d60 100644 --- a/lib/src/actions/file/chown.rs +++ b/lib/src/actions/file/chown.rs @@ -64,7 +64,7 @@ mod tests { user: test "#; - let mut actions: Vec = serde_yml::from_str(yaml).unwrap(); + let mut actions: Vec = serde_yaml_ng::from_str(yaml).unwrap(); match actions.pop() { Some(Actions::FileChown(action)) => { assert_eq!("/home/test/one", action.action.path); @@ -85,7 +85,7 @@ mod tests { group: test "#; - let mut actions: Vec = serde_yml::from_str(yaml).unwrap(); + let mut actions: Vec = serde_yaml_ng::from_str(yaml).unwrap(); match actions.pop() { Some(Actions::FileChown(action)) => { assert_eq!("/home/test/one", action.action.path); diff --git a/lib/src/actions/file/copy.rs b/lib/src/actions/file/copy.rs index d86969b1..2a6162e3 100644 --- a/lib/src/actions/file/copy.rs +++ b/lib/src/actions/file/copy.rs @@ -186,7 +186,7 @@ mod tests { chmod: "0777" "#; - let mut actions: Vec = serde_yml::from_str(yaml).unwrap(); + let mut actions: Vec = serde_yaml_ng::from_str(yaml).unwrap(); match actions.pop() { Some(Actions::FileCopy(action)) => { @@ -211,7 +211,7 @@ mod tests { owned_by_group: test "#; - let mut actions: Vec = serde_yml::from_str(yaml).unwrap(); + let mut actions: Vec = serde_yaml_ng::from_str(yaml).unwrap(); match actions.pop() { Some(Actions::FileCopy(action)) => { diff --git a/lib/src/actions/file/download.rs b/lib/src/actions/file/download.rs index 1d19523a..b6eefe4a 100644 --- a/lib/src/actions/file/download.rs +++ b/lib/src/actions/file/download.rs @@ -126,7 +126,7 @@ mod tests { to: b "#; - let mut actions: Vec = serde_yml::from_str(yaml).unwrap(); + let mut actions: Vec = serde_yaml_ng::from_str(yaml).unwrap(); match actions.pop() { Some(Actions::FileDownload(action)) => { @@ -150,7 +150,7 @@ mod tests { owned_by_group: test "#; - let mut actions: Vec = serde_yml::from_str(yaml).unwrap(); + let mut actions: Vec = serde_yaml_ng::from_str(yaml).unwrap(); match actions.pop() { Some(Actions::FileDownload(action)) => { diff --git a/lib/src/actions/file/link.rs b/lib/src/actions/file/link.rs index b00f10b4..5fa89660 100644 --- a/lib/src/actions/file/link.rs +++ b/lib/src/actions/file/link.rs @@ -161,7 +161,7 @@ mod tests { target: b "#; - let mut actions: Vec = serde_yml::from_str(yaml).unwrap(); + let mut actions: Vec = serde_yaml_ng::from_str(yaml).unwrap(); match actions.pop() { Some(Actions::FileLink(action)) => { @@ -180,7 +180,7 @@ mod tests { to: b "#; - let mut actions: Vec = serde_yml::from_str(yaml).unwrap(); + let mut actions: Vec = serde_yaml_ng::from_str(yaml).unwrap(); match actions.pop() { Some(Actions::FileLink(action)) => { @@ -253,9 +253,9 @@ mod tests { let number_of_files: usize = rng.random_range(3..9); for i in 0..number_of_files { - let path = source_dir.clone().join(format!("{}.txt", i)); + let path = source_dir.clone().join(format!("{i}.txt")); let mut file = std::fs::File::create(path).unwrap(); - writeln!(file, "Random {}", i).unwrap(); + writeln!(file, "Random {i}").unwrap(); } let manifest: Manifest = Manifest { diff --git a/lib/src/actions/file/remove.rs b/lib/src/actions/file/remove.rs index 0c6dcd08..56d33976 100644 --- a/lib/src/actions/file/remove.rs +++ b/lib/src/actions/file/remove.rs @@ -51,7 +51,7 @@ mod tests { target: a "#; - let mut actions: Vec = serde_yml::from_str(yaml).unwrap(); + let mut actions: Vec = serde_yaml_ng::from_str(yaml).unwrap(); match actions.pop() { Some(Actions::FileRemove(action)) => { diff --git a/lib/src/actions/file/unarchive.rs b/lib/src/actions/file/unarchive.rs index bad6059d..4e3d3d84 100644 --- a/lib/src/actions/file/unarchive.rs +++ b/lib/src/actions/file/unarchive.rs @@ -53,7 +53,7 @@ mod tests { to: b "#; - let mut actions: Vec = serde_yml::from_str(yaml).unwrap(); + let mut actions: Vec = serde_yaml_ng::from_str(yaml).unwrap(); match actions.pop() { Some(Actions::FileUnarchive(action)) => { diff --git a/lib/src/actions/mod.rs b/lib/src/actions/mod.rs index 62a6d62b..087d00ce 100644 --- a/lib/src/actions/mod.rs +++ b/lib/src/actions/mod.rs @@ -252,7 +252,7 @@ impl Display for Actions { Actions::Plugin(_) => "plugin", }; - write!(f, "{}", name) + write!(f, "{name}") } } @@ -271,7 +271,7 @@ pub struct ActionError { impl From for ActionError { fn from(e: E) -> Self { ActionError { - message: format!("{}", e), + message: format!("{e}"), } } } @@ -301,7 +301,7 @@ actions: - where: Debian command: halt "#; - let m: Manifest = serde_yml::from_str(content).unwrap(); + let m: Manifest = serde_yaml_ng::from_str(content).unwrap(); let action = &m.actions[0]; diff --git a/lib/src/actions/package/install.rs b/lib/src/actions/package/install.rs index abab7828..d566d86e 100644 --- a/lib/src/actions/package/install.rs +++ b/lib/src/actions/package/install.rs @@ -81,7 +81,7 @@ mod tests { - bash "#; - let mut actions: Vec = serde_yml::from_str(yaml).unwrap(); + let mut actions: Vec = serde_yaml_ng::from_str(yaml).unwrap(); match actions.pop() { Some(Actions::PackageInstall(action)) => { diff --git a/lib/src/actions/package/providers/aptitude.rs b/lib/src/actions/package/providers/aptitude.rs index 3402a6b9..edc32bb0 100644 --- a/lib/src/actions/package/providers/aptitude.rs +++ b/lib/src/actions/package/providers/aptitude.rs @@ -81,9 +81,9 @@ impl PackageProvider for Aptitude { let key = repository.clone().key.unwrap(); let key_name = key.name.unwrap_or_else(|| digest(&*key.url)); - let key_path = format!("/usr/share/keyrings/{}.asc", key_name); + let key_path = format!("/usr/share/keyrings/{key_name}.asc"); - signed_by = format!("signed-by={}", key_path); + signed_by = format!("signed-by={key_path}"); steps.push(Step { atom: Box::new(Exec { diff --git a/lib/src/actions/package/providers/mod.rs b/lib/src/actions/package/providers/mod.rs index b08689ca..c9da1cb4 100644 --- a/lib/src/actions/package/providers/mod.rs +++ b/lib/src/actions/package/providers/mod.rs @@ -90,7 +90,7 @@ impl Default for PackageProviders { fn default() -> Self { let info = os_info::get(); - println!("Info: {:?}", info); + println!("Info: {info:?}"); match info.os_type() { // Arch Variants diff --git a/lib/src/actions/plugin/plugin.rs b/lib/src/actions/plugin/plugin.rs index 270657c8..36f14072 100644 --- a/lib/src/actions/plugin/plugin.rs +++ b/lib/src/actions/plugin/plugin.rs @@ -90,7 +90,7 @@ impl Display for Version { Version::Tagged(tag) => tag.as_str(), }; - write!(f, "{}", version) + write!(f, "{version}") } } @@ -174,7 +174,7 @@ impl Source for Repo { }, Version::Latest => repo.head_tree()?, Version::Tagged(ref version) => repo - .find_reference(&format!("tags/{}", version))? + .find_reference(&format!("tags/{version}"))? .peel_to_tree()?, }; @@ -244,8 +244,8 @@ pub enum RepoOrDir { impl Display for RepoOrDir { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - RepoOrDir::Repo(repo) => write!(f, "{}", repo), - RepoOrDir::Dir(dir) => write!(f, "{}", dir), + RepoOrDir::Repo(repo) => write!(f, "{repo}"), + RepoOrDir::Dir(dir) => write!(f, "{dir}"), RepoOrDir::Invalid => write!(f, "Invalid Repo or Directory"), } } @@ -297,7 +297,7 @@ impl Plugin { impl Display for Plugin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Plugin: {:?}", self) + write!(f, "Plugin: {self:?}") } } diff --git a/lib/src/atoms/file/unarchive.rs b/lib/src/atoms/file/unarchive.rs index 5c2132a0..6c0119ba 100644 --- a/lib/src/atoms/file/unarchive.rs +++ b/lib/src/atoms/file/unarchive.rs @@ -58,8 +58,7 @@ impl std::fmt::Display for Unarchive { write!( f, - "The archive {} to be decompressed to {}", - origin_path, dest_path + "The archive {origin_path} to be decompressed to {dest_path}" ) } } diff --git a/lib/src/contexts/mod.rs b/lib/src/contexts/mod.rs index a099dd67..94cadecb 100644 --- a/lib/src/contexts/mod.rs +++ b/lib/src/contexts/mod.rs @@ -106,7 +106,7 @@ pub fn to_rhai(context: &Contexts) -> rhai::Scope<'_> { let dynamic = match rhai::serde::to_dynamic(v) { Ok(dynamic) => dynamic, Err(error) => { - panic!("Failed to convert context value to dynamic: {}", error); + panic!("Failed to convert context value to dynamic: {error}"); } }; diff --git a/lib/src/contexts/privilege.rs b/lib/src/contexts/privilege.rs index ff6cd3a3..44dc6c33 100644 --- a/lib/src/contexts/privilege.rs +++ b/lib/src/contexts/privilege.rs @@ -22,7 +22,7 @@ impl Display for Privilege { Privilege::Doas => "doas".to_string(), Privilege::Run0 => "run0".to_string(), }; - write!(f, "{}", str) + write!(f, "{str}") } } diff --git a/lib/src/contexts/variable_include/file.rs b/lib/src/contexts/variable_include/file.rs index 1d7d85f9..63236772 100644 --- a/lib/src/contexts/variable_include/file.rs +++ b/lib/src/contexts/variable_include/file.rs @@ -21,7 +21,7 @@ pub fn yaml_values(url: &Url, contexts: &mut HashMap) -> Result< let path = url.path(); let contents = std::fs::read_to_string(path)?; - let values: HashMap = serde_yml::from_str(&contents)?; + let values: HashMap = serde_yaml_ng::from_str(&contents)?; for (key, value) in values { contexts.insert(key.to_string(), value.to_string()); diff --git a/lib/src/manifests/load.rs b/lib/src/manifests/load.rs index 2a5637b9..a90e2df1 100644 --- a/lib/src/manifests/load.rs +++ b/lib/src/manifests/load.rs @@ -84,7 +84,7 @@ pub fn load(manifest_path: PathBuf, contexts: &Contexts) -> HashMap { - serde_yml::from_str::(template.deref()).map_err(anyhow::Error::from) + serde_yaml_ng::from_str::(template.deref()).map_err(anyhow::Error::from) } Some("toml") => toml::from_str::(template.deref()).map_err(anyhow::Error::from), _ => { diff --git a/lib/src/tera_functions/mod.rs b/lib/src/tera_functions/mod.rs index 04ccbd17..8cee37fb 100644 --- a/lib/src/tera_functions/mod.rs +++ b/lib/src/tera_functions/mod.rs @@ -12,8 +12,7 @@ impl Function for ReadFileContents { }, None => Err(format!( - "Path: '{}'. Error: Cannot convert argument 'path' to str", - value + "Path: '{value}'. Error: Cannot convert argument 'path' to str" ) .into()), }, @@ -47,7 +46,7 @@ SXOE "#; - write!(file.as_file_mut(), "{}", file_content)?; + write!(file.as_file_mut(), "{file_content}")?; let template = format!( "{{{{ read_file_contents(path=\"{}\") }}}}", diff --git a/lib/src/values/mod.rs b/lib/src/values/mod.rs index 1a2603db..018cf71b 100644 --- a/lib/src/values/mod.rs +++ b/lib/src/values/mod.rs @@ -159,8 +159,8 @@ impl Debug for Value { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Value::Null => formatter.write_str("Null"), - Value::String(string) => write!(formatter, "String({:?})", string), - Value::Number(number) => write!(formatter, "Number({})", number), + Value::String(string) => write!(formatter, "String({string:?})"), + Value::Number(number) => write!(formatter, "Number({number})"), Value::List(list) => { formatter.write_str("List ")?; formatter.debug_list().entries(list).finish() @@ -171,7 +171,7 @@ impl Debug for Value { impl Debug for Number { fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "Number({})", self) + write!(formatter, "Number({self})") } }