aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/mozart-registry/src/inline_package.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/mozart-registry/src/inline_package.rs')
-rw-r--r--crates/mozart-registry/src/inline_package.rs60
1 files changed, 60 insertions, 0 deletions
diff --git a/crates/mozart-registry/src/inline_package.rs b/crates/mozart-registry/src/inline_package.rs
index 509193b..a7df987 100644
--- a/crates/mozart-registry/src/inline_package.rs
+++ b/crates/mozart-registry/src/inline_package.rs
@@ -77,6 +77,64 @@ pub fn collect_inline_packages(repositories: &[RawRepository]) -> Vec<InlinePack
packages
}
+/// One advisory extracted from a repository's `security-advisories` block.
+/// Carries enough to filter affected versions out of the pool when
+/// `config.audit.block-insecure` is set, matching the slice of Composer's
+/// `SecurityAdvisoryPoolFilter` Mozart needs for resolution-time blocking.
+#[derive(Debug, Clone)]
+pub struct SecurityAdvisory {
+ pub advisory_id: String,
+ pub affected_versions: String,
+}
+
+/// Collect every `security-advisories` entry across all repositories.
+/// Returned map is keyed by lowercase package name so the resolver can
+/// look up affected versions in lockstep with the rest of its
+/// case-insensitive name handling. Repository order is preserved within
+/// each list.
+pub fn collect_security_advisories(
+ repositories: &[RawRepository],
+) -> indexmap::IndexMap<String, Vec<SecurityAdvisory>> {
+ let mut out: indexmap::IndexMap<String, Vec<SecurityAdvisory>> = indexmap::IndexMap::new();
+ for repo in repositories {
+ let Some(advisories) = &repo.security_advisories else {
+ continue;
+ };
+ let Some(map) = advisories.as_object() else {
+ continue;
+ };
+ for (pkg_name, list) in map {
+ let Some(arr) = list.as_array() else {
+ continue;
+ };
+ for entry in arr {
+ let Some(obj) = entry.as_object() else {
+ continue;
+ };
+ let Some(affected) = obj
+ .get("affectedVersions")
+ .and_then(|v| v.as_str())
+ .map(String::from)
+ else {
+ continue;
+ };
+ let advisory_id = obj
+ .get("advisoryId")
+ .and_then(|v| v.as_str())
+ .map(String::from)
+ .unwrap_or_default();
+ out.entry(pkg_name.to_lowercase())
+ .or_default()
+ .push(SecurityAdvisory {
+ advisory_id,
+ affected_versions: affected,
+ });
+ }
+ }
+ }
+ out
+}
+
fn parse_inline_package(value: &serde_json::Value) -> Option<InlinePackage> {
let obj = value.as_object()?;
let name = obj.get("name")?.as_str()?.to_string();
@@ -114,6 +172,7 @@ mod tests {
only: None,
exclude: None,
canonical: None,
+ security_advisories: None,
}
}
@@ -151,6 +210,7 @@ mod tests {
only: None,
exclude: None,
canonical: None,
+ security_advisories: None,
}];
assert!(collect_inline_packages(&repos).is_empty());
}