Skip to main content

git_lore/lore/
sanitize.rs

1use super::LoreAtom;
2
3#[derive(Clone, Debug, PartialEq, Eq)]
4pub struct SanitizationIssue {
5    pub atom_id: String,
6    pub field: String,
7    pub reason: String,
8}
9
10pub fn scan_atoms(atoms: &[LoreAtom]) -> Vec<SanitizationIssue> {
11    let mut issues = Vec::new();
12
13    for atom in atoms {
14        if let Some(reason) = scan_text(&atom.title) {
15            issues.push(SanitizationIssue {
16                atom_id: atom.id.clone(),
17                field: "title".to_string(),
18                reason,
19            });
20        }
21
22        if let Some(body) = atom.body.as_deref() {
23            if let Some(reason) = scan_text(body) {
24                issues.push(SanitizationIssue {
25                    atom_id: atom.id.clone(),
26                    field: "body".to_string(),
27                    reason,
28                });
29            }
30        }
31    }
32
33    issues
34}
35
36pub fn scan_text(text: &str) -> Option<String> {
37    let lowered = text.to_ascii_lowercase();
38
39    let markers = [
40        ("api key", "possible API key disclosure"),
41        ("secret", "possible secret disclosure"),
42        ("token", "possible token disclosure"),
43        ("password", "possible password disclosure"),
44        ("private key", "possible private key disclosure"),
45        ("-----begin", "possible private key block"),
46        ("akia", "possible AWS key disclosure"),
47        ("xoxb-", "possible Slack token disclosure"),
48        ("ghp_", "possible GitHub token disclosure"),
49        ("AIza", "possible Google API key disclosure"),
50    ];
51
52    markers
53        .iter()
54        .find(|(needle, _)| lowered.contains(*needle))
55        .map(|(_, reason)| reason.to_string())
56}