Skip to main content

security_rust/data/
mail_header.rs

1// Copyright (c) 2026 erik <erik@erik.xyz> — https://erik.xyz
2
3use crate::{AttackCategory, DetectionResult, Detector, Severity};
4use regex::Regex;
5use std::sync::LazyLock;
6
7static PATTERNS: LazyLock<Vec<Regex>> = LazyLock::new(|| {
8    vec![
9        Regex::new(r"(?i)Bcc\s*:").unwrap(),
10        Regex::new(r"(?i)Cc\s*:").unwrap(),
11        Regex::new(r"(?i)From\s*:.*\r?\n.*From\s*:").unwrap(),
12        Regex::new(r"(?i)MIME-Version\s*:").unwrap(),
13        Regex::new(r"(?i)Content-Type\s*:.*multipart").unwrap(),
14        Regex::new(r"(?i)boundary\s*=").unwrap(),
15    ]
16});
17
18pub struct MailHeaderDetector;
19
20impl Detector for MailHeaderDetector {
21    fn name(&self) -> &'static str {
22        "mail_header"
23    }
24
25    fn detect(&self, input: &str) -> Option<DetectionResult> {
26        for re in PATTERNS.iter() {
27            if let Some(m) = re.find(input) {
28                return Some(DetectionResult {
29                    attack_type: "mail_header".into(),
30                    category: AttackCategory::Data,
31                    severity: Severity::Medium,
32                    matched_pattern: m.as_str().to_string(),
33                    offset: m.start(),
34                    message: "Mail header injection detected".into(),
35                });
36            }
37        }
38        None
39    }
40}