{"record":{"id":"6ce380e69cd14c91","repo":"openai/codex","slug":"mitm-hook-hosts-must-be-exact-hosts-and-cannot-con","errorCode":null,"errorMessage":"MITM hook hosts must be exact hosts and cannot contain wildcards","messagePattern":"MITM hook hosts must be exact hosts and cannot contain wildcards","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"codex-rs/network-proxy/src/mitm_hook.rs","lineNumber":542,"sourceCode":"    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()\n        .map(|method| {\n            let normalized = method.trim().to_ascii_uppercase();\n            if normalized.is_empty() {\n                return Err(anyhow!(\"methods must not contain empty entries\"));\n            }\n            Ok(normalized)\n        })\n        .collect()\n}","sourceCodeStart":524,"sourceCodeEnd":560,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/network-proxy/src/mitm_hook.rs#L524-L560","documentation":"MITM hooks are stored in a BTreeMap keyed by the request's normalized host, so each hook needs one exact host. normalize_hook_host therefore rejects any host containing '*' after normalization with 'MITM hook hosts must be exact hosts and cannot contain wildcards' — unlike allow/block host policy, hook hosts cannot be globbed.","triggerScenarios":"host = \"*.example.com\", host = \"api.*\", or any host whose normalized form still contains '*' in a [[network.mitm_hooks]] entry; raised from validate_mitm_hook_config (context 'invalid network.mitm_hooks[i].host') and compile_mitm_hooks_with_resolvers.","commonSituations":"Reusing wildcard host patterns from network allowlist policy in hook config; trying to cover many subdomains with a single hook; porting config from tools that allow wildcard vhosts.","solutions":["Replace the wildcard with one exact host per hook, e.g. host = \"api.example.com\"","Duplicate (or generate) the hook block for each subdomain you need to intercept","Keep wildcard matching in the host allow/block policy, where it is supported, and reserve hooks for exact hosts"],"exampleFix":"# before\n[[network.mitm_hooks]]\nhost = \"*.example.com\"\n\n# after — one hook per exact host\n[[network.mitm_hooks]]\nhost = \"api.example.com\"\n\n[[network.mitm_hooks]]\nhost = \"cdn.example.com\"","handlingStrategy":"validation","validationCode":"// Rust — hook hosts must be exact\nfor (i, hook) in config.mitm_hooks.iter().enumerate() {\n    if hook.host.contains('*') {\n        return Err(anyhow!(\"network.mitm_hooks[{i}].host must be an exact host\"));\n    }\n}","typeGuard":"fn hook_host_is_exact(hook: &MitmHookConfig) -> bool {\n    !hook.host.contains('*')\n}","tryCatchPattern":"match validate_mitm_hook_config(&config) {\n    Ok(()) => {}\n    Err(err) => eprintln!(\"{err:#}\"), // 'invalid network.mitm_hooks[i].host: MITM hook hosts must be exact hosts...'\n}","preventionTips":["Expand wildcard hosts into one hook per subdomain at config-generation time","Keep wildcard matching in allow/block policy, not hook config","Spell out the exact hosts you need to intercept when writing hooks"],"tags":["network","mitm","codex","config-validation","hostname","wildcard"],"backgroundTag":"wildcard-host-not-supported","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}