{"record":{"id":"dafeba068c247879","repo":"jlcodes99/cockpit-tools","slug":"email-regex-should-be-valid","errorCode":null,"errorMessage":"email regex should be valid","messagePattern":"email regex should be valid","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"info","filePath":"crates/cockpit-core/src/modules/logger.rs","lineNumber":20,"sourceCode":"use chrono::{DateTime, Duration, Local};\nuse regex::{Captures, Regex};\nuse std::fs;\nuse std::fs::File;\nuse std::io::{Read, Seek, SeekFrom};\nuse std::path::{Path, PathBuf};\nuse std::sync::LazyLock;\nuse tracing::{error, info, warn};\nuse tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};\n\nconst LOG_FILE_PREFIX: &str = \"app.log\";\nconst LOG_RETENTION_DAYS: i64 = 3;\nconst DEFAULT_LOG_TAIL_LINES: usize = 200;\nconst MIN_LOG_TAIL_LINES: usize = 20;\nconst MAX_LOG_TAIL_LINES: usize = 5000;\nconst LOG_TAIL_SCAN_CHUNK_BYTES: usize = 8192;\nstatic EMAIL_REGEX: LazyLock<Regex> = LazyLock::new(|| {\n    Regex::new(r\"(?i)\\b[a-z0-9._%+\\-]+@[a-z0-9.\\-]+\\.[a-z]{2,}\\b\")\n        .expect(\"email regex should be valid\")\n});\n\nstruct LocalTimer;\n\nimpl tracing_subscriber::fmt::time::FormatTime for LocalTimer {\n    fn format_time(&self, w: &mut tracing_subscriber::fmt::format::Writer<'_>) -> std::fmt::Result {\n        let now = chrono::Local::now();\n        write!(w, \"{}\", now.to_rfc3339())\n    }\n}\n\npub fn get_log_dir() -> Result<PathBuf, String> {\n    let data_dir = get_data_dir()?;\n    let log_dir = data_dir.join(\"logs\");\n\n    if !log_dir.exists() {\n        fs::create_dir_all(&log_dir).map_err(|e| format!(\"创建日志目录失败: {}\", e))?;\n    }","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/crates/cockpit-core/src/modules/logger.rs#L2-L38","documentation":"The logger builds a static LazyLock<Regex> used to redact email addresses from log output, calling .expect(\"email regex should be valid\"). Since the pattern is a compile-time constant that is known-valid, this panic can only fire if the regex source in the code is edited into an invalid form — a developer/build-time defect, not a runtime input problem.","triggerScenarios":"Logger initialization when the hardcoded regex literal is invalid — i.e. only after someone edits the EMAIL_REGEX pattern with a syntax error, bad escape, or an unsupported feature for the installed regex crate version.","commonSituations":"Hand-editing the redaction pattern (e.g. adding a lookahead, which the regex crate does not support); upgrading/downgrading the regex crate across feature changes; copy-pasting a PCRE-style pattern into the Rust regex crate.","solutions":["Validate the pattern with regex::Regex::new in a unit test or quick check before building.","Fix the regex syntax; remove PCRE-only constructs (lookarounds, backreferences) unsupported by the regex crate.","If pattern validity must be dynamic, replace .expect with graceful error handling returning a no-redaction fallback.","Pin/align the regex crate version if a feature used by the pattern disappeared."],"exampleFix":"// before\nRegex::new(r\"(?i)\\b[a-z0-9._%+\\-]+(?=@)[a-z0-9.@]+\\b\")\n    .expect(\"email regex should be valid\") // lookahead: unsupported -> panic\n\n// after\nRegex::new(r\"(?i)\\b[a-z0-9._%+\\-]+@[a-z0-9.\\-]+\\.[a-z]{2,}\\b\")\n    .expect(\"email regex should be valid\")","handlingStrategy":"validation","validationCode":"#[cfg(test)]\n#[test]\nfn email_regex_is_valid() {\n    Regex::new(r\"(?i)\\b[a-z0-9._%+\\-]+@[a-z0-9.\\-]+\\.[a-z]{2,}\\b\")\n        .expect(\"email regex should be valid\");\n}","typeGuard":null,"tryCatchPattern":"static EMAIL_REGEX: LazyLock<Option<Regex>> = LazyLock::new(|| {\n    Regex::new(r\"(?i)\\b[a-z0-9._%+\\-]+@[a-z0-9.\\-]+\\.[a-z]{2,}\\b\").ok()\n}); // redact only when Some","preventionTips":["Add a unit test asserting the redaction regex compiles","Avoid PCRE-only constructs (lookarounds, backreferences) — the regex crate rejects them","Lint regex literals in code review when touching logger redaction rules","Pin the regex crate version so pattern features stay supported"],"tags":["regex","panic","logging","compile-time"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}