atuin_client/
secrets.rs

1// This file will probably trigger a lot of scanners. Sorry.
2
3pub enum TestValue<'a> {
4    Single(&'a str),
5    Multiple(&'a [&'a str]),
6}
7
8// A list of (name, regex, test), where test should match against regex
9pub static SECRET_PATTERNS: &[(&str, &str, TestValue)] = &[
10    (
11        "AWS Access Key ID",
12        "AKIA[0-9A-Z]{16}",
13        TestValue::Single("AKIAIOSFODNN7EXAMPLE"),
14    ),
15    (
16        "AWS secret access key env var",
17        "AWS_ACCESS_KEY_ID",
18        TestValue::Single("export AWS_ACCESS_KEY_ID=KEYDATA"),
19    ),
20    (
21        "AWS secret access key env var",
22        "AWS_ACCESS_KEY_ID",
23        TestValue::Single("export AWS_ACCESS_KEY_ID=KEYDATA"),
24    ),
25    (
26        "Microsoft Azure secret access key env var",
27        "AZURE_.*_KEY",
28        TestValue::Single("export AZURE_STORAGE_ACCOUNT_KEY=KEYDATA"),
29    ),
30    (
31        "Google cloud platform key env var",
32        "GOOGLE_SERVICE_ACCOUNT_KEY",
33        TestValue::Single("export GOOGLE_SERVICE_ACCOUNT_KEY=KEYDATA"),
34    ),
35    (
36        "Atuin login",
37        r"atuin\s+login",
38        TestValue::Single("atuin login -u mycoolusername -p mycoolpassword -k \"lots of random words\""),
39    ),
40    (
41        "GitHub PAT (old)",
42        "ghp_[a-zA-Z0-9]{36}",
43        TestValue::Single("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"), // legit, I expired it
44    ),
45    (
46        "GitHub PAT (new)",
47        "gh1_[A-Za-z0-9]{21}_[A-Za-z0-9]{59}|github_pat_[0-9][A-Za-z0-9]{21}_[A-Za-z0-9]{59}",
48        TestValue::Multiple(&[
49            "gh1_1234567890abcdefghijk_1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklm",
50            "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", // also legit, also expired
51        ])
52    ),
53    (
54        "GitHub OAuth Access Token",
55        "gho_[A-Za-z0-9]{36}",
56        TestValue::Single("gho_1234567890abcdefghijklmnopqrstuvwx000"),  // not a real token
57    ),
58    (
59        "GitHub OAuth Access Token (user)",
60        "ghu_[A-Za-z0-9]{36}",
61        TestValue::Single("ghu_1234567890abcdefghijklmnopqrstuvwx000"),  // not a real token
62    ),
63    (
64        "GitHub App Installation Access Token",
65        "ghs_[A-Za-z0-9]{36}",
66        TestValue::Single("ghs_1234567890abcdefghijklmnopqrstuvwx000"),  // not a real token
67    ),
68    (
69        "GitHub Refresh Token",
70        "ghr_[A-Za-z0-9]{76}",
71        TestValue::Single("ghr_1234567890abcdefghijklmnopqrstuvwx1234567890abcdefghijklmnopqrstuvwx1234567890abcdefghijklmnopqrstuvwx"),  // not a real token
72    ),
73    (
74        "GitHub App Installation Access Token v1",
75        "v1\\.[0-9A-Fa-f]{40}",
76        TestValue::Single("v1.1234567890abcdef1234567890abcdef12345678"),  // not a real token
77    ),
78    (
79        "GitLab PAT",
80        "glpat-[a-zA-Z0-9_]{20}",
81        TestValue::Single("glpat-RkE_BG5p_bbjML21WSfy"),
82    ),
83    (
84        "Slack OAuth v2 bot",
85        "xoxb-[0-9]{11}-[0-9]{11}-[0-9a-zA-Z]{24}",
86        TestValue::Single("xoxb-17653672481-19874698323-pdFZKVeTuE8sk7oOcBrzbqgy"),
87    ),
88    (
89        "Slack OAuth v2 user token",
90        "xoxp-[0-9]{11}-[0-9]{11}-[0-9a-zA-Z]{24}",
91        TestValue::Single("xoxp-17653672481-19874698323-pdFZKVeTuE8sk7oOcBrzbqgy"),
92    ),
93    (
94        "Slack webhook",
95        "T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8}/[a-zA-Z0-9_]{24}",
96        TestValue::Single("https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"),
97    ),
98    ("Stripe test key", "sk_test_[0-9a-zA-Z]{24}", TestValue::Single("sk_test_1234567890abcdefghijklmnop")),
99    ("Stripe live key", "sk_live_[0-9a-zA-Z]{24}", TestValue::Single("sk_live_1234567890abcdefghijklmnop")),
100    (
101        "Netlify authentication token",
102        "nf[pcoub]_[0-9a-zA-Z]{36}",
103        TestValue::Single("nfp_nBh7BdJxUwyaBBwFzpyD29MMFT6pZ9wq5634"),
104    ),
105    (
106        "npm token",
107        "npm_[A-Za-z0-9]{36}",
108        TestValue::Single("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"),
109    ),
110    (
111        "Pulumi personal access token",
112        "pul-[0-9a-f]{40}",
113        TestValue::Single("pul-683c2770662c51d960d72ec27613be7653c5cb26"),
114    ),
115];
116
117#[cfg(test)]
118mod tests {
119    use regex::Regex;
120
121    use crate::secrets::{TestValue, SECRET_PATTERNS};
122
123    #[test]
124    fn test_secrets() {
125        for (name, regex, test) in SECRET_PATTERNS {
126            let re =
127                Regex::new(regex).unwrap_or_else(|_| panic!("Failed to compile regex for {name}"));
128
129            match test {
130                TestValue::Single(test) => {
131                    assert!(re.is_match(test), "{name} test failed!");
132                }
133                TestValue::Multiple(tests) => {
134                    for test_str in tests.iter() {
135                        assert!(
136                            re.is_match(test_str),
137                            "{name} test with value \"{test_str}\" failed!"
138                        );
139                    }
140                }
141            }
142        }
143    }
144}