use rustinel_core::{analyze_diff, analyze_lockfile, AnalysisOptions, CrateMetadata};
use std::collections::BTreeMap;
use std::path::PathBuf;
fn fixtures() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../fixtures")
}
fn meta(owners: &[&str], days: Option<u64>) -> CrateMetadata {
CrateMetadata {
published_days_ago: days,
owners: owners.iter().map(|s| (*s).to_string()).collect(),
..Default::default()
}
}
fn hermetic(
trusted: BTreeMap<String, Vec<String>>,
metadata: BTreeMap<String, CrateMetadata>,
) -> AnalysisOptions {
AnalysisOptions {
offline: true,
advisory_db_path: Some(PathBuf::from("/nonexistent-rustinel-proactive-test-db")),
trusted_owners: trusted,
metadata,
..Default::default()
}
}
#[test]
fn xz_new_maintainer_flagged_before_any_advisory() {
let lock = fixtures().join("attacks/xz/Cargo.lock");
let trusted = BTreeMap::from([("liblzma-rs".to_string(), vec!["larhzu".to_string()])]);
let metadata = BTreeMap::from([(
"liblzma-rs@5.6.1".to_string(),
meta(&["larhzu", "jiaT75"], None),
)]);
let report = analyze_lockfile(&lock, hermetic(trusted, metadata)).unwrap();
let finding = report
.findings
.iter()
.find(|f| f.id == "owners_changed")
.expect("the new maintainer must be flagged");
assert_eq!(finding.package, "liblzma-rs@5.6.1");
}
#[test]
fn event_stream_new_owner_and_fresh_dep_flagged_before_any_advisory() {
let base = fixtures().join("attacks/event-stream/base.lock");
let head = fixtures().join("attacks/event-stream/head.lock");
let trusted = BTreeMap::from([("eventstream".to_string(), vec!["dominictarr".to_string()])]);
let metadata = BTreeMap::from([
(
"eventstream@3.3.6".to_string(),
meta(&["dominictarr", "right9ctrl"], None),
),
("flatmap-stream@0.1.1".to_string(), meta(&[], Some(2))),
]);
let report = analyze_diff(&base, &head, hermetic(trusted, metadata)).unwrap();
assert!(
report
.findings
.iter()
.any(|f| f.id == "owners_changed" && f.package == "eventstream@3.3.6"),
"the new maintainer must be flagged",
);
assert!(
report
.findings
.iter()
.any(|f| f.id == "freshly_published" && f.package == "flatmap-stream@0.1.1"),
"the freshly added dependency must be flagged",
);
}
#[test]
fn faster_log_class_exfil_domain_flagged_statically() {
let lock = fixtures().join("attacks/faster-log/Cargo.lock");
let options = AnalysisOptions {
offline: true,
advisory_db_path: Some(PathBuf::from("/nonexistent-rustinel-proactive-test-db")),
source_path: Some(fixtures().join("mock_registry")),
..Default::default()
};
let report = analyze_lockfile(&lock, options).unwrap();
assert!(
report
.findings
.iter()
.any(|f| f.id == "suspicious_exfil_domain" && f.package == "faster-log@0.1.0"),
"the *.workers.dev exfil endpoint must be flagged",
);
assert!(
!report
.findings
.iter()
.any(|f| f.id == "suspicious_source_exfil" && f.package == "faster-log@0.1.0"),
"source-scan fingerprint should NOT fire (the crate reads logs, not .rs)",
);
}
#[test]
fn rustdecimal_env_gated_payload_flagged_statically() {
let lock = fixtures().join("attacks/rustdecimal/Cargo.lock");
let options = AnalysisOptions {
offline: true,
advisory_db_path: Some(PathBuf::from("/nonexistent-rustinel-proactive-test-db")),
source_path: Some(fixtures().join("mock_registry")),
..Default::default()
};
let report = analyze_lockfile(&lock, options).unwrap();
assert!(
report
.findings
.iter()
.any(|f| f.id == "env_gated_payload" && f.package == "rustdecimal@0.1.0"),
"the env-gated download-and-execute must be flagged",
);
}
#[test]
fn dependency_confusion_popular_name_from_non_crates_io_flagged() {
let lock = fixtures().join("attacks/dependency-confusion/Cargo.lock");
let options = AnalysisOptions {
offline: true,
advisory_db_path: Some(PathBuf::from("/nonexistent-rustinel-proactive-test-db")),
..Default::default()
};
let report = analyze_lockfile(&lock, options).unwrap();
assert!(
report
.findings
.iter()
.any(|f| f.id == "source_substitution" && f.package == "serde@1.0.219"),
"a popular crate name from a non-crates.io source must be flagged",
);
assert!(
report
.policy
.review_items
.iter()
.chain(report.policy.violations.iter())
.any(|s| s.contains("serde")),
"the substitution must surface in the policy decision (review/violation)",
);
}
#[test]
fn dependency_confusion_on_known_good_crate_is_not_a_silent_pass() {
let lock = fixtures().join("attacks/dependency-confusion-known-good/Cargo.lock");
let options = AnalysisOptions {
offline: true,
advisory_db_path: Some(PathBuf::from("/nonexistent-rustinel-proactive-test-db")),
..Default::default()
};
let report = analyze_lockfile(&lock, options).unwrap();
assert!(
report
.findings
.iter()
.any(|f| f.id == "source_substitution" && f.package == "libc@0.2.0"),
"the signal must survive the known-good baseline (libc is known-good)",
);
assert!(
report
.policy
.review_items
.iter()
.chain(report.policy.violations.iter())
.any(|s| s.contains("libc")),
"dependency confusion on a known-good crate must surface in the decision, not be a silent pass",
);
}
#[test]
fn benign_http_client_trips_no_malice_signals() {
let lock = fixtures().join("attacks/benign/Cargo.lock");
let options = AnalysisOptions {
offline: true,
advisory_db_path: Some(PathBuf::from("/nonexistent-rustinel-proactive-test-db")),
source_path: Some(fixtures().join("mock_registry")),
..Default::default()
};
let report = analyze_lockfile(&lock, options).unwrap();
for pkg in ["legit-api-client@0.1.0", "benign-codegen@0.1.0"] {
for id in [
"suspicious_exfil_domain",
"env_gated_payload",
"suspicious_source_exfil",
"source_substitution",
] {
assert!(
!report
.findings
.iter()
.any(|f| f.id == id && f.package == pkg),
"benign crate `{pkg}` must not trip `{id}`",
);
}
}
}