keyhog-core 0.5.44

keyhog-core: shared data model and detector specifications for the KeyHog secret scanner
Documentation
use std::ffi::OsString;
use std::sync::Mutex;
use tempfile::TempDir;

static ENV_LOCK: Mutex<()> = Mutex::new(());

fn with_xdg_cache_home(test: impl FnOnce(&TempDir)) {
    let _guard = ENV_LOCK.lock().unwrap_or_else(|err| err.into_inner());
    let cache_home = TempDir::new().expect("cache tempdir");
    let previous = std::env::var_os("XDG_CACHE_HOME");
    unsafe { std::env::set_var("XDG_CACHE_HOME", cache_home.path()) };

    test(&cache_home);

    restore_env("XDG_CACHE_HOME", previous);
}

fn restore_env(key: &str, previous: Option<OsString>) {
    unsafe {
        match previous {
            Some(value) => std::env::set_var(key, value),
            None => std::env::remove_var(key),
        }
    }
}

fn compiled_hyperscan_cache_name() -> String {
    format!("hs-{}.db", "a".repeat(64))
}

fn compiled_hyperscan_cache_bytes() -> Vec<u8> {
    let mut bytes = Vec::new();
    bytes.extend_from_slice(b"KHHS");
    bytes.extend_from_slice(&keyhog_core::HYPERSCAN_CACHE_VERSION.to_le_bytes());
    bytes.extend_from_slice(b"serialized-hyperscan-body");
    bytes
}

#[test]
fn empty_keyhog_cache_dir_is_not_lockdown_violation() {
    with_xdg_cache_home(|cache_home| {
        let keyhog_cache = cache_home.path().join("keyhog");
        std::fs::create_dir_all(&keyhog_cache).expect("create empty cache dir");

        assert!(
            keyhog_core::testing::CoreTestApi::lockdown_disk_cache_violations(
                &keyhog_core::testing::TestApi,
            )
            .is_empty(),
            "empty keyhog cache dir must not fail lockdown"
        );
    });
}

#[test]
fn compiled_hyperscan_cache_file_is_not_lockdown_violation() {
    with_xdg_cache_home(|cache_home| {
        let keyhog_cache = cache_home.path().join("keyhog");
        std::fs::create_dir_all(&keyhog_cache).expect("create cache dir");
        std::fs::write(
            keyhog_cache.join(compiled_hyperscan_cache_name()),
            compiled_hyperscan_cache_bytes(),
        )
        .expect("write compiled cache");

        assert!(
            keyhog_core::testing::CoreTestApi::lockdown_disk_cache_violations(
                &keyhog_core::testing::TestApi,
            )
            .is_empty(),
            "exact-shape compiled Hyperscan cache with current KHHS header must not fail lockdown"
        );
    });
}

#[test]
fn hs_db_without_compiled_cache_header_is_lockdown_violation() {
    with_xdg_cache_home(|cache_home| {
        let keyhog_cache = cache_home.path().join("keyhog");
        std::fs::create_dir_all(&keyhog_cache).expect("create cache dir");
        std::fs::write(keyhog_cache.join(compiled_hyperscan_cache_name()), b"[]\n")
            .expect("write fake hs cache");

        assert_eq!(
            keyhog_core::testing::CoreTestApi::lockdown_disk_cache_violations(
                &keyhog_core::testing::TestApi,
            ),
            vec![keyhog_cache],
            "an hs-named file without the compiled-cache marker must fail lockdown"
        );
    });
}

#[test]
fn loose_hs_db_filename_is_lockdown_violation_even_with_cache_header() {
    with_xdg_cache_home(|cache_home| {
        let keyhog_cache = cache_home.path().join("keyhog");
        std::fs::create_dir_all(&keyhog_cache).expect("create cache dir");
        std::fs::write(
            keyhog_cache.join("hs-findings.db"),
            compiled_hyperscan_cache_bytes(),
        )
        .expect("write loose-name cache");

        assert_eq!(
            keyhog_core::testing::CoreTestApi::lockdown_disk_cache_violations(
                &keyhog_core::testing::TestApi,
            ),
            vec![keyhog_cache],
            "loose hs-*.db names must not bypass the past-findings cache gate"
        );
    });
}

#[test]
fn non_empty_keyhog_cache_dir_is_lockdown_violation() {
    with_xdg_cache_home(|cache_home| {
        let keyhog_cache = cache_home.path().join("keyhog");
        std::fs::create_dir_all(&keyhog_cache).expect("create cache dir");
        std::fs::write(keyhog_cache.join("findings.json"), b"[]\n").expect("write cache content");

        assert_eq!(
            keyhog_core::testing::CoreTestApi::lockdown_disk_cache_violations(
                &keyhog_core::testing::TestApi,
            ),
            vec![keyhog_cache],
            "non-empty keyhog cache dir must fail lockdown"
        );
    });
}

#[test]
fn configured_incremental_cache_file_is_lockdown_violation() {
    with_xdg_cache_home(|cache_home| {
        let custom_root = cache_home.path().join("custom");
        std::fs::create_dir_all(&custom_root).expect("create custom cache dir");
        let custom_cache = custom_root.join("merkle.idx");
        std::fs::write(&custom_cache, b"cached metadata\n").expect("write custom merkle cache");

        assert_eq!(
            keyhog_core::testing::CoreTestApi::lockdown_disk_cache_violations_for_paths(
                &keyhog_core::testing::TestApi,
                vec![custom_cache.clone()],
            ),
            vec![custom_cache],
            "lockdown must inspect configured incremental cache files outside the default root"
        );
    });
}

#[test]
fn cache_entry_read_error_is_lockdown_violation() {
    assert!(
        keyhog_core::testing::CoreTestApi::lockdown_cache_entry_error_is_violation(
            &keyhog_core::testing::TestApi,
        ),
        "a per-entry read_dir error must fail closed instead of being filtered out"
    );
}