{"record":{"id":"eb9b88a28b93308a","repo":"openai/codex","slug":"invalid-glob-pattern-pattern-err","errorCode":null,"errorMessage":"invalid glob pattern {pattern:?}: {err}","messagePattern":"invalid glob pattern (.+?): (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"codex-rs/network-proxy/src/mitm_hook.rs","lineNumber":533,"sourceCode":"    };\n    if glob_pattern.is_empty() {\n        return Err(anyhow!(\"glob pattern must not be empty\"));\n    }\n    Ok(MatcherPattern::Glob(glob_pattern))\n}\n\nfn compile_glob_matcher(pattern: &str, literal_separator: bool) -> Result<CompiledGlobMatcher> {\n    let mut builder = GlobBuilder::new(pattern);\n    builder\n        .backslash_escape(true)\n        .literal_separator(literal_separator);\n    builder\n        .build()\n        .map(|glob| CompiledGlobMatcher {\n            pattern: pattern.to_string(),\n            matcher: glob.compile_matcher(),\n        })\n        .map_err(|err| anyhow!(\"invalid glob pattern {pattern:?}: {err}\"))\n}\n\nfn normalize_hook_host(host: &str) -> Result<String> {\n    let normalized = normalize_host(host);\n    if normalized.is_empty() {\n        return Err(anyhow!(\"host must not be empty\"));\n    }\n    if normalized.contains('*') {\n        return Err(anyhow!(\n            \"MITM hook hosts must be exact hosts and cannot contain wildcards\"\n        ));\n    }\n    Ok(normalized)\n}\n\nfn normalize_methods(methods: &[String]) -> Result<Vec<String>> {\n    methods\n        .iter()","sourceCodeStart":515,"sourceCodeEnd":551,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/network-proxy/src/mitm_hook.rs#L515-L551","documentation":"Strings prefixed with 'pattern:' are compiled by compile_glob_matcher via globset's GlobBuilder with backslash_escape(true) and literal_separator(true) for paths (false for query/header values). Patterns globset cannot parse — unclosed character classes like '[a-z', unterminated alternations like '{a,b', or bad backslash escapes — surface as 'invalid glob pattern {pattern:?}: {err}'.","triggerScenarios":"path_prefixes = [\"pattern:[unclosed\"], query allowed-values like \"pattern:{a\", or header matchers with a dangling backslash — any 'pattern:' entry for which GlobBuilder::build returns an error, from compile_path_matchers or compile_value_matchers.","commonSituations":"Assuming regex or plain shell-glob semantics instead of globset syntax; forgetting to escape '[' when matching a literal bracket; pasting complex alternations from other tools' configs.","solutions":["Fix the globset syntax: close every [class] and {alt,a,b}, and escape literal metacharacters with a backslash","Wrap literal text containing glob metacharacters with the 'literal:' prefix instead, e.g. \"literal:v[1]\"","Remember '*' does not cross '/' in path matchers (literal_separator = true) but does in query/header values","Dry-run patterns with GlobBuilder::new(p).backslash_escape(true).literal_separator(true).build() before shipping config"],"exampleFix":"# before — unclosed alternation\npath_prefixes = [\"pattern:/api/{v\"]\n\n# after\npath_prefixes = [\"pattern:/api/{v1,v2}\"]","handlingStrategy":"validation","validationCode":"// Rust — pre-compile globs exactly like compile_glob_matcher does\nuse globset::GlobBuilder;\nfn glob_ok(pattern: &str, literal_separator: bool) -> bool {\n    GlobBuilder::new(pattern)\n        .backslash_escape(true)\n        .literal_separator(literal_separator)\n        .build()\n        .is_ok()\n}\n// paths use literal_separator = true; query/header values use false","typeGuard":"fn matcher_pattern_compiles(v: &str, literal_separator: bool) -> bool {\n    match v.strip_prefix(\"pattern:\") {\n        Some(glob) => glob_ok(glob, literal_separator),\n        None => true, // literal\n    }\n}","tryCatchPattern":"match compile_mitm_hooks(&config) {\n    Ok(_) => {}\n    Err(err) => eprintln!(\"{err:#}\"), // embeds the bad pattern verbatim plus globset's parse error\n}","preventionTips":["Dry-run every pattern: value through GlobBuilder with the same options the crate uses","Use literal: for text containing glob metacharacters","Remember * does not cross / in path patterns but does in query/header values"],"tags":["network","mitm","codex","config-validation","glob","globset","path-matching"],"backgroundTag":"invalid-glob-pattern","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}