use sha2::{Sha256, Digest};
use std::fs;
use std::path::Path;
use tracing::warn;
const ALLOWED_HASHES: &[&str] = &[
];
pub fn verify_binary(binary_path: &Path) -> Result<(), String> {
if std::env::var("DSCODE_SKIP_NODE_VERIFY").is_ok() {
warn!("Node.js binary verification skipped (DSCODE_SKIP_NODE_VERIFY set)");
return Ok(());
}
if ALLOWED_HASHES.is_empty() {
return Ok(());
}
let hash = compute_file_hash(binary_path)?;
if ALLOWED_HASHES.contains(&hash.as_str()) {
Ok(())
} else {
Err(format!(
"Node.js binary hash mismatch: {} (expected one of: {:?})",
hash, ALLOWED_HASHES
))
}
}
fn compute_file_hash(path: &Path) -> Result<String, String> {
let data = fs::read(path)
.map_err(|e| format!("Failed to read binary {:?}: {}", path, e))?;
let mut hasher = Sha256::new();
hasher.update(&data);
let result = hasher.finalize();
Ok(format!("{:x}", result))
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Write;
#[test]
fn test_compute_file_hash() {
let dir = tempfile::tempdir().unwrap();
let file_path = dir.path().join("test_binary");
let mut file = fs::File::create(&file_path).unwrap();
file.write_all(b"test content").unwrap();
drop(file);
let hash = compute_file_hash(&file_path).unwrap();
assert_eq!(hash.len(), 64); assert!(!hash.is_empty());
}
#[test]
fn test_verify_binary_skips_with_env() {
std::env::set_var("DSCODE_SKIP_NODE_VERIFY", "1");
let result = verify_binary(Path::new("/nonexistent"));
std::env::remove_var("DSCODE_SKIP_NODE_VERIFY");
assert!(result.is_ok());
}
#[test]
fn test_verify_binary_skips_empty_hashes() {
let result = verify_binary(Path::new("/nonexistent"));
assert!(result.is_ok());
}
}