From b3a61a2e951469619688187908a0e2575e4cb82b Mon Sep 17 00:00:00 2001 From: "Abdulaziz M. Shehri" Date: Wed, 26 Aug 2026 18:27:48 +0300 Subject: [PATCH 1/3] fix(pkg): bound local mirror archive reads --- crates/commandf-pkg/src/source.rs | 41 +++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/crates/commandf-pkg/src/source.rs b/crates/commandf-pkg/src/source.rs index 7da9da5d..89df1186 100644 --- a/crates/commandf-pkg/src/source.rs +++ b/crates/commandf-pkg/src/source.rs @@ -1,10 +1,13 @@ use std::fs; +use std::io::Read; use std::path::{Path, PathBuf}; use semver::Version; use crate::{PackageError, PackageName}; +pub(crate) const MAX_PACKAGE_ARCHIVE_BYTES: u64 = 128 * 1024 * 1024; + #[derive(Clone, Debug, Eq, PartialEq)] pub struct PackageArchive { pub bytes: Vec, @@ -83,7 +86,7 @@ impl PackageSource for LocalMirrorSource { .join(name.as_str()) .join(version.to_string()) .join("package.tgz"); - fs::read(path).map_err(|error| { + let file = fs::File::open(path).map_err(|error| { if error.kind() == std::io::ErrorKind::NotFound { PackageError::PackageNotFound { name: name.to_string(), @@ -92,6 +95,40 @@ impl PackageSource for LocalMirrorSource { } else { PackageError::Io(error) } - }) + })?; + read_bounded_archive(file, MAX_PACKAGE_ARCHIVE_BYTES) + } +} + +fn read_bounded_archive(reader: R, max_bytes: u64) -> Result, PackageError> { + let mut bytes = Vec::new(); + reader + .take(max_bytes.saturating_add(1)) + .read_to_end(&mut bytes)?; + if bytes.len() as u64 > max_bytes { + return Err(PackageError::InvalidRequest(format!( + "package archive exceeds the maximum supported compressed size of {max_bytes} bytes" + ))); + } + Ok(bytes) +} + +#[cfg(test)] +mod tests { + use std::io::Cursor; + + use super::*; + + #[test] + fn bounded_archive_reader_accepts_exact_limit() { + let bytes = read_bounded_archive(Cursor::new(b"abcd"), 4).expect("exact bound"); + assert_eq!(bytes, b"abcd"); + } + + #[test] + fn bounded_archive_reader_rejects_limit_plus_one() { + let error = read_bounded_archive(Cursor::new(b"abcde"), 4) + .expect_err("limit plus one must fail closed"); + assert!(matches!(error, PackageError::InvalidRequest(_))); } } From fdd698a6be52307836f5b8aea6e84c4d5a37c4c8 Mon Sep 17 00:00:00 2001 From: "Abdulaziz M. Shehri" Date: Wed, 26 Aug 2026 18:28:30 +0300 Subject: [PATCH 2/3] refactor(pkg): share compressed archive size limit --- crates/commandf-pkg/src/registry.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/commandf-pkg/src/registry.rs b/crates/commandf-pkg/src/registry.rs index 781cb41c..c48d00d3 100644 --- a/crates/commandf-pkg/src/registry.rs +++ b/crates/commandf-pkg/src/registry.rs @@ -5,13 +5,14 @@ use semver::Version; use serde::Deserialize; use ureq::Agent; -use crate::{PackageArchive, PackageError, PackageName, PackageSource}; +use crate::{ + source::MAX_PACKAGE_ARCHIVE_BYTES, PackageArchive, PackageError, PackageName, PackageSource, +}; const PRIMARY: &str = "https://packages.fhir.org"; const SECONDARY: &str = "https://packages2.fhir.org/packages"; const SECONDARY_TARBALL_BASE: &str = "https://packages2.fhir.org/web"; const METADATA_LIMIT: u64 = 4 * 1024 * 1024; -const ARCHIVE_LIMIT: u64 = 128 * 1024 * 1024; const REQUEST_TIMEOUT: Duration = Duration::from_secs(30); const GZIP_MAGIC: [u8; 2] = [0x1f, 0x8b]; @@ -147,7 +148,7 @@ fn read_archive_body( response .body_mut() .with_config() - .limit(ARCHIVE_LIMIT) + .limit(MAX_PACKAGE_ARCHIVE_BYTES) .read_to_vec() .map_err(|error| format!("registry archive body from {url} failed: {error}")) } @@ -334,7 +335,7 @@ mod tests { assert!(archive.bytes.starts_with(&GZIP_MAGIC)); assert_eq!( archive.source, - "https://packages.fhir.org/hl7.fhir.us.core/8.0.1" + "https://packages.fhir.org/hl7.fhir.r4.core/4.0.1" ); } From a7dbda4eac62adf8aaff15519ac3876ce4828d74 Mon Sep 17 00:00:00 2001 From: "Abdulaziz M. Shehri" Date: Wed, 26 Aug 2026 18:29:10 +0300 Subject: [PATCH 3/3] test(pkg): preserve registry smoke expectation --- crates/commandf-pkg/src/registry.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/commandf-pkg/src/registry.rs b/crates/commandf-pkg/src/registry.rs index c48d00d3..b1f6518a 100644 --- a/crates/commandf-pkg/src/registry.rs +++ b/crates/commandf-pkg/src/registry.rs @@ -335,7 +335,7 @@ mod tests { assert!(archive.bytes.starts_with(&GZIP_MAGIC)); assert_eq!( archive.source, - "https://packages.fhir.org/hl7.fhir.r4.core/4.0.1" + "https://packages.fhir.org/hl7.fhir.us.core/8.0.1" ); }