fix: harden Cub git and tempdir handling

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-05-07 21:14:48 +01:00
parent f5e0ae82f4
commit e8fbf10f68
3 changed files with 28 additions and 20 deletions
@@ -18,6 +18,7 @@ redox-pkg = { git = "https://gitlab.redox-os.org/redox-os/pkgutils.git", default
clap = { workspace = true }
pkgar = "0.2.2"
pkgar-core = "0.2.2"
tempfile = "3"
termion = "4.0.6"
[features]
@@ -145,6 +145,7 @@ impl AppContext {
}
fn open_library(&self) -> Result<Library, pkg::backend::Error> {
self.ensure_install_layout()?;
let callback = new_pkg_callback();
Library::new(&self.install_path, &self.target, callback)
}
@@ -154,6 +155,7 @@ impl AppContext {
source_dir: &Path,
pubkey_dir: &Path,
) -> Result<Library, pkg::backend::Error> {
self.ensure_install_layout()?;
let callback = new_pkg_callback();
Library::new_local(
source_dir,
@@ -163,6 +165,11 @@ impl AppContext {
callback,
)
}
fn ensure_install_layout(&self) -> Result<(), pkg::backend::Error> {
fs::create_dir_all(self.install_path.join("etc/pkg.d"))?;
Ok(())
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -542,6 +549,7 @@ fn fetch_bur_recipe(package: &str) -> Result<(), Box<dyn std::error::Error>> {
}
fn get_aur_recipe(package: &str) -> Result<(), Box<dyn std::error::Error>> {
validate_git_target(package)?;
let repo_url = aur_repo_url(package);
let clone_dir = create_temp_dir("cub-aur-get")?;
@@ -549,6 +557,7 @@ fn get_aur_recipe(package: &str) -> Result<(), Box<dyn std::error::Error>> {
.arg("clone")
.arg("--depth")
.arg("1")
.arg("--")
.arg(&repo_url)
.arg(&clone_dir)
.status()?;
@@ -609,6 +618,7 @@ fn inspect_target(context: &AppContext, target: &str) -> Result<(), Box<dyn std:
}
fn import_aur_target(target: &str) -> Result<(), Box<dyn std::error::Error>> {
validate_git_target(target)?;
let repo_url = aur_repo_url(target);
let clone_dir = create_temp_dir("cub-aur")?;
@@ -616,6 +626,7 @@ fn import_aur_target(target: &str) -> Result<(), Box<dyn std::error::Error>> {
.arg("clone")
.arg("--depth")
.arg("1")
.arg("--")
.arg(&repo_url)
.arg(&clone_dir)
.status()?;
@@ -1151,25 +1162,8 @@ fn render_conversion_report(report: &ConversionReport) -> String {
}
fn create_temp_dir(prefix: &str) -> Result<PathBuf, Box<dyn std::error::Error>> {
let base = env::temp_dir();
let nanos = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|duration| duration.as_nanos())
.unwrap_or(0);
for attempt in 0..128 {
let candidate = base.join(format!("{prefix}-{}-{nanos}-{attempt}", std::process::id()));
if !candidate.exists() {
fs::create_dir_all(&candidate)?;
return Ok(candidate);
}
}
Err(io::Error::new(
io::ErrorKind::AlreadyExists,
format!("failed to allocate temporary directory for {prefix}"),
)
.into())
let path = tempfile::Builder::new().prefix(prefix).tempdir()?.keep();
Ok(path)
}
fn copy_dir_recursive(src: &Path, dst: &Path) -> Result<(), Box<dyn std::error::Error>> {
@@ -1236,3 +1230,15 @@ fn yes_no(value: bool) -> &'static str {
"no"
}
}
fn validate_git_target(target: &str) -> Result<(), Box<dyn std::error::Error>> {
if target.trim_start().starts_with('-') {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("invalid git target: {target}"),
)
.into());
}
Ok(())
}
@@ -26,7 +26,8 @@ pkgar-core = { version = "0.2.2", optional = true }
pkgar-keys = { version = "0.2.2", optional = true }
# HTTP for source fetching
reqwest = { version = "0.12", default-features = false, features = ["blocking", "rustls-tls"], optional = true }
reqwest = { version = "0.12", default-features = false, features = ["blocking", "rustls-tls", "json"], optional = true }
serde_json = "1"
[features]
default = ["full"]