securegit 0.8.5

Zero-trust git replacement with 12 built-in security scanners, LLM redteam bridge, universal undo, durable backups, and a 50-tool MCP server
Documentation
use lazy_static::lazy_static;
use regex::Regex;

lazy_static! {
    static ref TOKEN_PATTERNS: Vec<Regex> = vec![
        // GitHub classic PATs
        Regex::new(r"ghp_[A-Za-z0-9]{36,}").unwrap(),
        // GitHub OAuth access tokens
        Regex::new(r"gho_[A-Za-z0-9]{36,}").unwrap(),
        // GitHub user-to-server tokens
        Regex::new(r"ghu_[A-Za-z0-9]{36,}").unwrap(),
        // GitHub server-to-server tokens
        Regex::new(r"ghs_[A-Za-z0-9]{36,}").unwrap(),
        // GitHub fine-grained PATs
        Regex::new(r"github_pat_[A-Za-z0-9_]{22,}").unwrap(),
        // GitLab personal access tokens
        Regex::new(r"glpat-[A-Za-z0-9\-_.]{20,}").unwrap(),
        // GitLab deploy tokens
        Regex::new(r"gldt-[A-Za-z0-9\-_.]{20,}").unwrap(),
        // Bearer/Token authorization headers
        Regex::new(r"(?i)(Bearer|Token|PRIVATE-TOKEN:?)\s+[A-Za-z0-9\-_.]{20,}").unwrap(),
        // URLs with embedded credentials: ://user:TOKEN@host
        Regex::new(r"://[^@\s]+@").unwrap(),
    ];
}

/// Sanitize output by redacting known credential patterns.
pub fn sanitize_output(input: &str) -> String {
    let mut result = input.to_string();
    for pattern in TOKEN_PATTERNS.iter() {
        result = pattern.replace_all(&result, "[REDACTED]").to_string();
    }
    result
}

/// Sanitize output, also redacting any occurrences of known token values.
pub fn sanitize_with_known_tokens(input: &str, known_tokens: &[&str]) -> String {
    let mut result = sanitize_output(input);
    for token in known_tokens {
        if !token.is_empty() {
            result = result.replace(token, "[REDACTED]");
        }
    }
    result
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_sanitize_github_pat() {
        let input = "token: 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";
        let result = sanitize_output(input);
        assert!(result.contains("[REDACTED]"));
        assert!(!result.contains("ghp_"));
    }

    #[test]
    fn test_sanitize_gitlab_pat() {
        let input = "auth: glpat-xxxxxxxxxxxxxxxxxxxx";
        let result = sanitize_output(input);
        assert!(result.contains("[REDACTED]"));
        assert!(!result.contains("glpat-"));
    }

    #[test]
    fn test_sanitize_fine_grained_github() {
        let input =
            "github_pat_11AAAAAA0xxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
        let result = sanitize_output(input);
        assert!(result.contains("[REDACTED]"));
        assert!(!result.contains("github_pat_"));
    }

    #[test]
    fn test_sanitize_bearer_header() {
        let input = "Authorization: Bearer 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";
        let result = sanitize_output(input);
        assert!(!result.contains("ghp_"));
    }

    #[test]
    fn test_sanitize_preserves_normal_text() {
        let input = "Pushed to origin/main successfully. 3 commits transferred.";
        let result = sanitize_output(input);
        assert_eq!(result, input);
    }

    #[test]
    fn test_sanitize_url_with_embedded_creds() {
        let input = "remote: http://user:mysecrettoken@gitlab.example.com/repo.git";
        let result = sanitize_output(input);
        assert!(!result.contains("mysecrettoken"));
        assert!(result.contains("[REDACTED]"));
    }

    #[test]
    fn test_sanitize_with_known_tokens() {
        let input = "Server responded with: abc123secretvalue in the output";
        let result = sanitize_with_known_tokens(input, &["abc123secretvalue"]);
        assert!(!result.contains("abc123secretvalue"));
        assert!(result.contains("[REDACTED]"));
    }

    #[test]
    fn test_sanitize_with_empty_known_tokens() {
        let input = "Normal output text";
        let result = sanitize_with_known_tokens(input, &[""]);
        assert_eq!(result, input);
    }

    #[test]
    fn test_sanitize_multiple_tokens_in_one_string() {
        let input =
            "ghp_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa and glpat-bbbbbbbbbbbbbbbbbbbbbbbb";
        let result = sanitize_output(input);
        assert!(!result.contains("ghp_"));
        assert!(!result.contains("glpat-"));
        assert_eq!(result.matches("[REDACTED]").count(), 2);
    }

    #[test]
    fn test_sanitize_gitlab_deploy_token() {
        let input = "deploy: gldt-xxxxxxxxxxxxxxxxxxxx";
        let result = sanitize_output(input);
        assert!(!result.contains("gldt-"));
        assert!(result.contains("[REDACTED]"));
    }

    #[test]
    fn test_sanitize_private_token_header() {
        let input = "PRIVATE-TOKEN: glpat-xxxxxxxxxxxxxxxxxxxx";
        let result = sanitize_output(input);
        assert!(!result.contains("glpat-"));
    }
}