use std::path::PathBuf;
use openclaw_scan::finding::{Category, Severity};
use openclaw_scan::paths::FrameworkHint;
use openclaw_scan::scanner::{secrets::SecretsScanner, ScanContext, Scanner};
fn fixture_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures")
}
fn ctx(root: PathBuf) -> ScanContext {
ScanContext { root, framework: FrameworkHint::Unknown }
}
#[test]
fn detects_secrets_in_history_with_secrets_jsonl() {
let dir = fixture_dir();
let tmp = tempfile::tempdir().unwrap();
std::fs::copy(
dir.join("history_with_secrets.jsonl"),
tmp.path().join("history.jsonl"),
)
.unwrap();
let scanner = SecretsScanner;
let findings = scanner.scan(&ctx(tmp.path().to_path_buf())).unwrap();
assert!(!findings.is_empty(), "Should detect secrets in history.jsonl");
assert!(
findings.iter().any(|f| f.category == Category::SecretDetection),
"Findings must be in SecretDetection category"
);
assert!(
findings
.iter()
.any(|f| f.severity >= Severity::High),
"At least one HIGH or CRITICAL finding expected"
);
}
#[test]
fn no_false_positives_on_clean_history() {
let dir = fixture_dir();
let tmp = tempfile::tempdir().unwrap();
std::fs::copy(
dir.join("history_clean.jsonl"),
tmp.path().join("history.jsonl"),
)
.unwrap();
let scanner = SecretsScanner;
let findings = scanner.scan(&ctx(tmp.path().to_path_buf())).unwrap();
assert!(
findings.is_empty(),
"Should not report false positives on clean history: {:?}",
findings
);
}
#[test]
fn detects_secrets_in_claude_md() {
let dir = fixture_dir();
let tmp = tempfile::tempdir().unwrap();
std::fs::copy(
dir.join("CLAUDE_with_secrets.md"),
tmp.path().join("CLAUDE.md"),
)
.unwrap();
let scanner = SecretsScanner;
let findings = scanner.scan(&ctx(tmp.path().to_path_buf())).unwrap();
assert!(!findings.is_empty(), "Should detect secrets in CLAUDE.md");
}
#[test]
fn evidence_is_always_redacted() {
let dir = fixture_dir();
let tmp = tempfile::tempdir().unwrap();
std::fs::copy(
dir.join("history_with_secrets.jsonl"),
tmp.path().join("history.jsonl"),
)
.unwrap();
let scanner = SecretsScanner;
let findings = scanner.scan(&ctx(tmp.path().to_path_buf())).unwrap();
for f in &findings {
if let Some(ref evidence) = f.evidence {
assert!(
evidence.ends_with("****"),
"Evidence should be redacted: {evidence}"
);
}
}
}