fix: robustesse v1.1.6 — timeout runner/doctor, anti-deadlock, securite migrate, win32 is_running, websocket RFC6455, keyring JSON
release / release (push) Successful in 13m38s
release / macos (push) Canceled after 0s

- runner.rs: timeout 30s sur les commandes capturees (doctor ne pend plus) + pipes stdout/stderr draines dans des threads (anti-deadlock) ; run_untimed() pour les installations longues (npm/cargo/go) — sh() des installateurs l'utilise, les sondes gardent le timeout

- migrate_cmd.rs: rejet des chemins unsafe (path traversal) dans import_bundle

- process.rs: is_running Windows via OpenProcess/GetExitCodeProcess (fiable vs tasklist)

- probe.rs: drain des pipes en threads dans detect_external_version

- web.rs: boucle de traduction i18n (curseur, plus de boucle infinie si la traduction contient {{)

- serve.rs: frames WebSocket RFC 6455 avec vraies longueurs > 125 octets (126/127)

- secrets.rs: index keyring serialise en JSON (cles contenant des virgules)

- sandbox.rs: tests sans fuite de TempDir (plus de mem::forget)

- version 1.1.6, man pages et ROADMAP maj
This commit is contained in:
2026-08-26 10:17:17 -04:00
parent fa2c42d505
commit d911ce5d92
13 changed files with 212 additions and 50 deletions
+23 -14
View File
@@ -30,7 +30,6 @@ impl ExternalInfo {
/// Detect the version of an external binary (--version), bounded by a
/// timeout so a misbehaving agent can never hang the whole listing.
pub fn detect_external_version(bin_path: &Path) -> Option<String> {
use std::io::Read;
let (prog, prefix) = crate::runner::resolve_program(&bin_path.display().to_string());
let mut cmd = std::process::Command::new(&prog);
cmd.args(&prefix)
@@ -41,6 +40,24 @@ pub fn detect_external_version(bin_path: &Path) -> Option<String> {
let Ok(mut child) = cmd.spawn() else {
return None;
};
let stdout_pipe = child.stdout.take();
let stderr_pipe = child.stderr.take();
let stdout_handle = std::thread::spawn(move || {
let mut out = String::new();
if let Some(mut pipe) = stdout_pipe {
let _ = std::io::Read::read_to_string(&mut pipe, &mut out);
}
out
});
let stderr_handle = std::thread::spawn(move || {
let mut err = String::new();
if let Some(mut pipe) = stderr_pipe {
let _ = std::io::Read::read_to_string(&mut pipe, &mut err);
}
err
});
const PROBE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(4);
let status: Option<std::process::ExitStatus> = match child.wait_timeout(PROBE_TIMEOUT) {
Ok(Some(s)) => Some(s),
@@ -51,22 +68,14 @@ pub fn detect_external_version(bin_path: &Path) -> Option<String> {
}
Err(_) => None,
};
let Some(status) = status else {
return None;
};
let stdout = stdout_handle.join().unwrap_or_default();
let stderr = stderr_handle.join().unwrap_or_default();
let status = status?;
if !status.success() {
return None;
}
let mut stdout = String::new();
let mut stderr = String::new();
if let Some(mut o) = child.stdout.take() {
let _ = o.read_to_string(&mut stdout);
}
if let Some(mut e) = child.stderr.take() {
let _ = e.read_to_string(&mut stderr);
}
let combined = format!("{stdout}
{stderr}");
let combined = format!("{stdout}\n{stderr}");
crate::version::find_version(&combined)
}