pub struct DependencyVulnerabilities {
pub advisories: Capped<Arc<Advisory>>,
pub upgrade_status: UpgradeStatus,
pub fix_target_status: UpgradeStatus,
}Expand description
Vulnerability data for one dependency that OSV reported as non-clean.
Fields§
§advisories: Capped<Arc<Advisory>>Advisories fetched in full, capped at crate::osv::ADVISORY_DISPLAY_CAP (invariant 3
in architecture.md §8: the fetch itself is capped, not only the render) — the total
advisory count OSV reported is carried alongside via Capped::total, independent of
how many were actually fetched, and is the source of the render layer’s “+N more
advisories” count (architecture.md §7/§8 invariant 3).
upgrade_status: UpgradeStatusResult of phase B’s “latest” check, if it has run for this dependency.
fix_target_status: UpgradeStatusIndependent verification of Self::recommended_fix’s target version F, if F
differs from the “latest” candidate upgrade_status already covers. Left at
UpgradeStatus::NotChecked until Self::recommended_fix has been computed and F’s
status resolved — either reused from upgrade_status when F equals latest, or checked
live via crate::osv::OsvClient::check_candidates otherwise (always live-checked when
F differs from latest: a data-derived shortcut was tried and rejected — see git history
on this field and #462’s critique — because it degenerates into checking F against
exactly the advisories it was computed from, proving nothing about an advisory phase
A never fetched at all, which is the actual gap #462 closes). See
run_osv_phase_b_and_commit in deps-lsp for the resolution order.
A caller must not treat a bare UpgradeStatus::CandidateClean check as the only valid
“verified” state: UpgradeStatus::CandidateVulnerable can also be a legitimate,
presentable fix when every reported id is an advisory Self::recommended_fix already
declined to claim (excluded via still_applying, or never had a known fix) — see
deps-core’s lsp_helpers::code_actions::fix_target_is_verified (the actual gate
generate_code_actions uses) for the full contract, rather than re-deriving it ad hoc.
Implementations§
Source§impl DependencyVulnerabilities
impl DependencyVulnerabilities
Sourcepub fn recommended_fix(&self) -> Option<FixRecommendation>
pub fn recommended_fix(&self) -> Option<FixRecommendation>
Recommends a single upgrade target that resolves as many of this dependency’s known advisories as possible.
advisory_ids is computed first: every advisory with a known fix,
minus — when phase B (UpgradeStatus::CandidateVulnerable) reports
that some ids still apply to the checked candidate — those ids,
since claiming a fix for them would be false. version is then the
highest Advisory::fixed_versions entry across only the
remaining claimed advisories, not every advisory: computing it over
the full set first would let an advisory this method just excluded
(because its own fix is known not to hold) drag the recommendation
past a lower version that already clears everything actually being
claimed. Returns None when no advisory has a claimable fix.
The subtraction’s premise is that the checked candidate is at least
as new as version; when phase B checked an older candidate the
subtraction is merely over-conservative (it only ever removes
claims), so this is documented rather than guarded against.
§Limitations
advisories is capped at fetch time
(crate::osv::ADVISORY_DISPLAY_CAP), so version is the max over a
possibly incomplete subset — the “+N more advisories” hint already
signals that incompleteness, so this is an accepted under-report, not
a bug. Advisory also retains only fixed_versions, never
introduced events, so a version reintroduced above its own last
known fix (and not yet re-fixed) can still be claimed as a fix
whenever phase B has not run for this dependency
(UpgradeStatus::NotChecked) — the post-edit rescan is what
surfaces that case.
§Examples
use deps_core::osv::{Advisory, Capped, DependencyVulnerabilities, UpgradeStatus, VulnSeverity};
use std::sync::Arc;
fn advisory(id: &str, fixed: &str) -> Arc<Advisory> {
Arc::new(Advisory {
id: id.to_string(),
modified: "2023-01-01T00:00:00Z".to_string(),
summary: None,
aliases: vec![],
severity: VulnSeverity::High,
cvss_vector: None,
fixed_versions: vec![fixed.to_string()],
url: String::new(),
})
}
let dv = DependencyVulnerabilities {
advisories: Capped::new(vec![advisory("RUSTSEC-1", "1.2.0")], 1),
upgrade_status: UpgradeStatus::NotChecked,
fix_target_status: UpgradeStatus::NotChecked,
};
let fix = dv.recommended_fix().unwrap();
assert_eq!(fix.version, "1.2.0");
assert_eq!(fix.advisory_ids, vec!["RUSTSEC-1".to_string()]);Trait Implementations§
Source§impl Clone for DependencyVulnerabilities
impl Clone for DependencyVulnerabilities
Source§fn clone(&self) -> DependencyVulnerabilities
fn clone(&self) -> DependencyVulnerabilities
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more