From fd3aca7cb3394d895d27e8cea26a02948b06d6f1 Mon Sep 17 00:00:00 2001 From: Chris Rose Date: Tue, 25 Jun 2024 13:24:31 -0700 Subject: [PATCH] feat: add several other GitHub access token patterns (#2200) - OAuth access tokens - refresh token - app installation token - PAT v2 Additionally, added support for having >1 value for testing, for cases where the pattern for a secret has alternative formats (GitHub PAT v2 does this) --- CHANGELOG.md | 1 + crates/atuin-client/src/secrets.rs | 81 +++++++++++++++++++++++------- 2 files changed, 64 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3580052..a0515d6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file. ### Features +- *(client)* Identify several other GitHub token types as secrets - *(daemon)* Follow XDG_RUNTIME_DIR if set ([#2171](https://github.com/atuinsh/atuin/issues/2171)) - *(gui)* Automatically install and setup the cli/shell ([#2139](https://github.com/atuinsh/atuin/issues/2139)) - *(gui)* Add activity calendar to the homepage ([#2160](https://github.com/atuinsh/atuin/issues/2160)) diff --git a/crates/atuin-client/src/secrets.rs b/crates/atuin-client/src/secrets.rs index 70786235..a94e21d3 100644 --- a/crates/atuin-client/src/secrets.rs +++ b/crates/atuin-client/src/secrets.rs @@ -1,76 +1,109 @@ // This file will probably trigger a lot of scanners. Sorry. +pub enum TestValue<'a> { + Single(&'a str), + Multiple(&'a [&'a str]), +} + // A list of (name, regex, test), where test should match against regex -pub static SECRET_PATTERNS: &[(&str, &str, &str)] = &[ +pub static SECRET_PATTERNS: &[(&str, &str, TestValue)] = &[ ( "AWS Access Key ID", "AKIA[0-9A-Z]{16}", - "AKIAIOSFODNN7EXAMPLE", + TestValue::Single("AKIAIOSFODNN7EXAMPLE"), ), ( "AWS secret access key env var", "AWS_ACCESS_KEY_ID", - "export AWS_ACCESS_KEY_ID=KEYDATA", + TestValue::Single("export AWS_ACCESS_KEY_ID=KEYDATA"), ), ( "AWS secret access key env var", "AWS_ACCESS_KEY_ID", - "export AWS_ACCESS_KEY_ID=KEYDATA", + TestValue::Single("export AWS_ACCESS_KEY_ID=KEYDATA"), ), ( "Microsoft Azure secret access key env var", "AZURE_.*_KEY", - "export AZURE_STORAGE_ACCOUNT_KEY=KEYDATA", + TestValue::Single("export AZURE_STORAGE_ACCOUNT_KEY=KEYDATA"), ), ( "Google cloud platform key env var", "GOOGLE_SERVICE_ACCOUNT_KEY", - "export GOOGLE_SERVICE_ACCOUNT_KEY=KEYDATA", + TestValue::Single("export GOOGLE_SERVICE_ACCOUNT_KEY=KEYDATA"), ), ( "Atuin login", r"atuin\s+login", - "atuin login -u mycoolusername -p mycoolpassword -k \"lots of random words\"", + TestValue::Single("atuin login -u mycoolusername -p mycoolpassword -k \"lots of random words\""), ), ( "GitHub PAT (old)", "ghp_[a-zA-Z0-9]{36}", - "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", // legit, I expired it + TestValue::Single("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"), // legit, I expired it ), ( "GitHub PAT (new)", - "github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}", - "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", // also legit, also expired + "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}", + TestValue::Multiple(&[ + "gh1_1234567890abcdefghijk_1234567890abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklm", + "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", // also legit, also expired + ]) + ), + ( + "GitHub OAuth Access Token", + "gho_[A-Za-z0-9]{36}", + TestValue::Single("gho_1234567890abcdefghijklmnopqrstuvwx000"), // not a real token + ), + ( + "GitHub OAuth Access Token (user)", + "ghu_[A-Za-z0-9]{36}", + TestValue::Single("ghu_1234567890abcdefghijklmnopqrstuvwx000"), // not a real token + ), + ( + "GitHub App Installation Access Token", + "ghs_[A-Za-z0-9]{36}", + TestValue::Single("ghs_1234567890abcdefghijklmnopqrstuvwx000"), // not a real token + ), + ( + "GitHub Refresh Token", + "ghr_[A-Za-z0-9]{76}", + TestValue::Single("ghr_1234567890abcdefghijklmnopqrstuvwx1234567890abcdefghijklmnopqrstuvwx1234567890abcdefghijklmnopqrstuvwx"), // not a real token + ), + ( + "GitHub App Installation Access Token v1", + "v1\\.[0-9A-Fa-f]{40}", + TestValue::Single("v1.1234567890abcdef1234567890abcdef12345678"), // not a real token ), ( "GitLab PAT", "glpat-[a-zA-Z0-9_]{20}", - "glpat-RkE_BG5p_bbjML21WSfy", + TestValue::Single("glpat-RkE_BG5p_bbjML21WSfy"), ), ( "Slack OAuth v2 bot", "xoxb-[0-9]{11}-[0-9]{11}-[0-9a-zA-Z]{24}", - "xoxb-17653672481-19874698323-pdFZKVeTuE8sk7oOcBrzbqgy", + TestValue::Single("xoxb-17653672481-19874698323-pdFZKVeTuE8sk7oOcBrzbqgy"), ), ( "Slack OAuth v2 user token", "xoxp-[0-9]{11}-[0-9]{11}-[0-9a-zA-Z]{24}", - "xoxp-17653672481-19874698323-pdFZKVeTuE8sk7oOcBrzbqgy", + TestValue::Single("xoxp-17653672481-19874698323-pdFZKVeTuE8sk7oOcBrzbqgy"), ), ( "Slack webhook", "T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8}/[a-zA-Z0-9_]{24}", - "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX", + TestValue::Single("https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"), ), - ("Stripe test key", "sk_test_[0-9a-zA-Z]{24}", "sk_test_1234567890abcdefghijklmnop"), - ("Stripe live key", "sk_live_[0-9a-zA-Z]{24}", "sk_live_1234567890abcdefghijklmnop"), + ("Stripe test key", "sk_test_[0-9a-zA-Z]{24}", TestValue::Single("sk_test_1234567890abcdefghijklmnop")), + ("Stripe live key", "sk_live_[0-9a-zA-Z]{24}", TestValue::Single("sk_live_1234567890abcdefghijklmnop")), ]; #[cfg(test)] mod tests { use regex::Regex; - use crate::secrets::SECRET_PATTERNS; + use crate::secrets::{TestValue, SECRET_PATTERNS}; #[test] fn test_secrets() { @@ -78,7 +111,19 @@ mod tests { let re = Regex::new(regex).unwrap_or_else(|_| panic!("Failed to compile regex for {name}")); - assert!(re.is_match(test), "{name} test failed!"); + match test { + TestValue::Single(test) => { + assert!(re.is_match(test), "{name} test failed!"); + } + TestValue::Multiple(tests) => { + for test_str in tests.iter() { + assert!( + re.is_match(test_str), + "{name} test with value \"{test_str}\" failed!" + ); + } + } + } } } }