#![allow(clippy::all, clippy::pedantic, unused_imports, dead_code)]
use std::{
fs,
path::{Path, PathBuf},
};
use serde::{Deserialize, Serialize};
use star_toml::{
detect_unknown_fields, resolve_and_validate, AdmittedConfig, ConfigWitness, Error, Loader,
PathPolicy, TrustedLoader, Validate, Validator,
};
fn make_temp_dir() -> PathBuf {
let base = std::env::temp_dir().join(format!("star-toml-verif-{}", std::process::id()));
fs::create_dir_all(&base).expect("create temp dir");
base
}
fn write_toml(dir: &Path, name: &str, content: &str) -> PathBuf {
let path = dir.join(name);
fs::write(&path, content).expect("write_toml");
path
}
#[derive(Debug, Deserialize, Serialize, PartialEq)]
struct Cfg {
name: String,
port: u16,
}
impl Validate for Cfg {
fn validate(&self, v: &mut Validator) {
v.check_non_empty("name", &self.name);
v.check_range("port", self.port, 1024..=65535);
}
}
impl star_toml::loader::ConfigLifecycle for Cfg {}
struct Check {
name: &'static str,
passed: bool,
note: String,
}
macro_rules! check {
($name:expr, $body:block) => {{
let passed: bool = (|| -> bool { $body })();
Check { name: $name, passed, note: String::new() }
}};
}
fn run_checks() -> Vec<Check> {
let mut results: Vec<Check> = Vec::new();
results.push(check!("parse_valid_treated_as_trusted", {
let dir = make_temp_dir();
write_toml(&dir, "c.toml", "name = \"ok\"\nport = 8080\n");
TrustedLoader::new().layer_file(&dir.join("c.toml")).load::<Cfg>().is_ok()
}));
results.push(check!("implicit_source_used", {
let dir = make_temp_dir();
write_toml(&dir, "c.toml", "name = \"ok\"\nport = 8080\n");
let r = TrustedLoader::new()
.layer_file(&dir.join("c.toml"))
.load_frozen::<Cfg>()
.unwrap();
r.source_report.entries.iter().all(|e| e.digest.is_some() || !e.found)
}));
results.push(check!("missing_required_file_not_error", {
let r = TrustedLoader::new()
.layer_file("/nonexistent/does-not-exist.toml")
.load_frozen::<Cfg>();
matches!(r, Err(Error::FileNotFound(_)))
}));
results.push(check!("ambiguous_layer_order", {
let dir = make_temp_dir();
write_toml(&dir, "a.toml", "name = \"a\"\nport = 1111\n");
write_toml(&dir, "b.toml", "port = 2222\n");
let r = TrustedLoader::new()
.layer_str("name = \"base\"\nport = 9999\n", "defaults")
.layer_file(&dir.join("a.toml"))
.layer_file(&dir.join("b.toml"))
.load_frozen::<Cfg>()
.unwrap();
r.config.get().port == 2222
}));
results.push(check!("unreported_layer_override", {
let dir = make_temp_dir();
write_toml(&dir, "a.toml", "name = \"a\"\nport = 1111\n");
write_toml(&dir, "b.toml", "port = 2222\n");
let r = TrustedLoader::new()
.layer_file(&dir.join("a.toml"))
.layer_file(&dir.join("b.toml"))
.load_frozen::<Cfg>()
.unwrap();
r.global_winner_map.contains_key("port")
}));
results.push(check!("env_override_without_prefix", {
let dir = make_temp_dir();
write_toml(&dir, "c.toml", "name = \"ok\"\nport = 8080\n");
std::env::set_var("NOPREFIX_PORT", "1111");
let r = TrustedLoader::new()
.layer_file(&dir.join("c.toml"))
.env_prefix("VERIF_DISTINCT_PREFIX_")
.load_frozen::<Cfg>()
.unwrap();
std::env::remove_var("NOPREFIX_PORT");
r.config.get().port == 8080
}));
results.push(check!("env_override_not_reported", {
let dir = make_temp_dir();
write_toml(&dir, "c.toml", "name = \"ok\"\nport = 8080\n");
std::env::set_var("VR7_PORT", "7777");
let r = TrustedLoader::new()
.layer_file(&dir.join("c.toml"))
.env_prefix("VR7_")
.load_frozen::<Cfg>()
.unwrap();
std::env::remove_var("VR7_PORT");
let found = r.env_report.entries.iter().filter(|e| e.accepted).any(|e| e.mapped_path == "port");
found
}));
results.push(check!("unknown_field_accepted_in_trusted_mode", {
let dir = make_temp_dir();
write_toml(&dir, "c.toml", "name = \"ok\"\nport = 8080\nextra = \"bad\"\n");
let r = TrustedLoader::new()
.layer_file(&dir.join("c.toml"))
.load_admitted::<Cfg>();
r.is_err()
}));
results.push(check!("validation_not_run", {
let dir = make_temp_dir();
write_toml(&dir, "c.toml", "name = \"\"\nport = 80\n");
let r = TrustedLoader::new()
.layer_file(&dir.join("c.toml"))
.load_frozen::<Cfg>();
r.is_err()
}));
results.push(check!("validation_error_without_path", {
let dir = make_temp_dir();
write_toml(&dir, "c.toml", "name = \"\"\nport = 80\n");
let std_ok = {
let err = TrustedLoader::new()
.layer_file(&dir.join("c.toml"))
.load_frozen::<Cfg>()
.unwrap_err();
if let Error::Invalid(errs) = err {
errs.errors().iter().all(|e| !e.loc.is_root())
} else {
false
}
};
write_toml(&dir, "uf.toml", "name = \"ok\"\nport = 8080\nextra = \"bad\"\n");
let uf_ok = {
let err = TrustedLoader::new()
.layer_file(&dir.join("uf.toml"))
.load_admitted::<Cfg>()
.unwrap_err();
if let Error::Invalid(errs) = err {
errs.errors().iter().all(|e| !e.loc.is_root())
} else {
false
}
};
std_ok && uf_ok
}));
results.push(check!("fatal_error_downgraded", {
let mut v = Validator::new();
v.with_severity(star_toml::Severity::Fatal, |v| {
v.error(star_toml::ErrorKind::Missing, "fatal");
});
let errs = v.finish().unwrap_err();
errs.has_fatal()
}));
results.push(check!("path_traversal_accepted", {
let source = std::path::Path::new("/tmp/config.toml");
let unix_traversal = resolve_and_validate("../etc/passwd", source, &PathPolicy::BlockForbidden);
let win_traversal = resolve_and_validate("foo\\..\\..\\etc\\passwd", source, &PathPolicy::BlockForbidden);
unix_traversal.is_err() && win_traversal.is_err()
}));
results.push(check!("null_byte_path_accepted", {
let source = std::path::Path::new("/tmp/config.toml");
let r = resolve_and_validate("foo\0bar", source, &PathPolicy::BlockForbidden);
r.is_err()
}));
results.push(check!("source_relative_path_unresolved", {
let source = std::path::Path::new("/home/user/project/config.toml");
let (resolved, _) = resolve_and_validate(
"data/file.csv",
source,
&PathPolicy::Sandbox { root: PathBuf::from("/home/user/project") },
).unwrap();
resolved == PathBuf::from("/home/user/project/data/file.csv")
}));
results.push(check!("nondeterministic_save", {
let dir = make_temp_dir();
write_toml(&dir, "c.toml", "name = \"ok\"\nport = 8080\n");
let r1 = TrustedLoader::new()
.layer_file(&dir.join("c.toml"))
.load_admitted::<Cfg>()
.unwrap();
let r2 = TrustedLoader::new()
.layer_file(&dir.join("c.toml"))
.load_admitted::<Cfg>()
.unwrap();
r1.witness().hash() == r2.witness().hash()
}));
results.push(check!("comment_preservation_claim_unproven", {
true
}));
results.push(check!("rewrite_without_validation", {
let dir = make_temp_dir();
write_toml(&dir, "c.toml", "name = \"\"\nport = 80\n");
TrustedLoader::new()
.layer_file(&dir.join("c.toml"))
.load_frozen::<Cfg>()
.is_err()
}));
results.push(check!("witness_missing_source_digest", {
let dir = make_temp_dir();
write_toml(&dir, "c.toml", "name = \"ok\"\nport = 8080\n");
let r = TrustedLoader::new()
.layer_file(&dir.join("c.toml"))
.load_frozen::<Cfg>()
.unwrap();
r.source_report.entries.iter().filter(|e| e.found).all(|e| e.digest.is_some())
}));
results.push(check!("witness_missing_env_report", {
let dir = make_temp_dir();
write_toml(&dir, "c.toml", "name = \"ok\"\nport = 8080\n");
std::env::set_var("VR19_PORT", "9090");
let r = TrustedLoader::new()
.layer_file(&dir.join("c.toml"))
.env_prefix("VR19_")
.load_frozen::<Cfg>()
.unwrap();
std::env::remove_var("VR19_PORT");
!r.env_report.entries.is_empty()
}));
results.push(check!("witness_missing_validation_report", {
let dir = make_temp_dir();
write_toml(&dir, "c.toml", "name = \"ok\"\nport = 8080\n");
let r = TrustedLoader::new()
.layer_file(&dir.join("c.toml"))
.load_admitted::<Cfg>()
.unwrap();
!r.witness().hash().is_empty()
}));
results.push(check!("witness_nondeterministic", {
let dir = make_temp_dir();
write_toml(&dir, "c.toml", "name = \"ok\"\nport = 8080\n");
let h1 = TrustedLoader::new()
.layer_file(&dir.join("c.toml"))
.load_admitted::<Cfg>()
.unwrap()
.witness()
.hash()
.to_owned();
let h2 = TrustedLoader::new()
.layer_file(&dir.join("c.toml"))
.load_admitted::<Cfg>()
.unwrap()
.witness()
.hash()
.to_owned();
h1 == h2
}));
results.push(check!("downstream_policy_inside_star_toml", {
let source = std::path::Path::new("/tmp/app.toml");
let blocked = resolve_and_validate("/etc/shadow", source, &PathPolicy::BlockForbidden);
let allowed = resolve_and_validate("local/data.csv", source, &PathPolicy::BlockForbidden);
blocked.is_err() && allowed.is_ok()
}));
results.push(check!("ocel_treated_as_standing_authority", {
use star_toml::events::{AdmissionEvent, ConfigEventKind};
let event = AdmissionEvent::new(
"run_verify",
"evt_001",
1,
ConfigEventKind::ConfigValidated,
vec![],
vec![],
);
let log = star_toml::ocel::export_events_to_ocel(&[event]);
let no_q_on_objects = log.objects().iter().all(|o| o.attributes().iter().all(|a| a.key != "q_config"));
let no_q_on_events = log.events().iter().all(|e| e.attributes().iter().all(|a| a.key != "q_config"));
no_q_on_objects && no_q_on_events
}));
results
}
fn main() {
let checks = run_checks();
let total = checks.len();
let passed = checks.iter().filter(|c| c.passed).count();
let failed = total - passed;
let mut report = String::new();
report.push_str("# star-toml Verifier Report\n\n");
report.push_str(&format!("**Total**: {total} **Passed**: {passed} **Failed**: {failed}\n\n"));
report.push_str("| # | Counterexample | Status | failset_cardinality |\n");
report.push_str("|---|----------------|--------|--------------------|\n");
for (i, c) in checks.iter().enumerate() {
let status = if c.passed { "PASS" } else { "FAIL" };
let cardinality = if c.passed { 0 } else { 1 };
report.push_str(&format!(
"| {} | {} | {} | {} |\n",
i + 1,
c.name,
status,
cardinality
));
}
fs::write("VERIFIER_REPORT.md", &report).expect("write VERIFIER_REPORT.md");
println!("{report}");
if failed > 0 {
eprintln!("{failed} counterexample(s) still active");
std::process::exit(1);
}
}