diff --git a/src/utils.rs b/src/utils.rs index 8e3996f..e4bf4c1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -104,6 +104,17 @@ pub fn run_bitcoin_cli( profile: &Profile, args: &[String], ) -> Result { + let file_name = std::path::Path::new(&profile.bitcoin_cli) + .file_name() + .and_then(|n| n.to_str()) + .unwrap_or(""); + + if file_name != "bitcoin-cli" && file_name != "bitcoin-cli.exe" { + return Err(crate::error::AppError::Config( + "Invalid bitcoin-cli binary. Only 'bitcoin-cli' or 'bitcoin-cli.exe' are allowed for security reasons.".to_string(), + )); + } + let mut cmd = std::process::Command::new(&profile.bitcoin_cli); for arg in &profile.bitcoin_cli_args { cmd.arg(arg); diff --git a/src/wallet_service.rs b/src/wallet_service.rs index f9e7ef4..cb15d61 100644 --- a/src/wallet_service.rs +++ b/src/wallet_service.rs @@ -6,7 +6,6 @@ use rpassword::read_password; use std::fs; use std::io::{self, Write}; use std::path::{Path, PathBuf}; -use std::process::Command as ShellCommand; pub use zinc_core::{ decrypt_wallet_internal, encrypt_wallet_internal, generate_wallet_internal, @@ -226,27 +225,6 @@ pub fn persist_wallet_session(session: &mut WalletSession) -> Result<(), AppErro write_profile(&session.profile_path, &session.profile) } -#[allow(dead_code)] -pub fn run_bitcoin_cli(profile: &Profile, args: &[String]) -> Result { - let output = ShellCommand::new(&profile.bitcoin_cli) - .args(&profile.bitcoin_cli_args) - .args(args) - .output() - .map_err(|e| AppError::Config(format!("failed to launch {}: {e}", profile.bitcoin_cli)))?; - - if !output.status.success() { - let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string(); - let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string(); - let details = if !stderr.is_empty() { stderr } else { stdout }; - return Err(AppError::Network(format!( - "bitcoin-cli command failed: {} {}", - profile.bitcoin_cli, details - ))); - } - - Ok(String::from_utf8_lossy(&output.stdout).trim().to_string()) -} - #[cfg(test)] mod tests { use super::*;