{"record":{"id":"72e6e1c9eb7c12bc","repo":"BigPizzaV3/CodexPlusPlus","slug":"base-url-72e6e1","errorCode":null,"errorMessage":"Base URL 不得指向本机或私有网络","messagePattern":"Base URL 不得指向本机或私有网络","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/routes.rs","lineNumber":780,"sourceCode":"        \"ok\": ok,\n        \"body_text\": body_text,\n        \"body_json\": body_json,\n    }))\n}\n\nfn validate_llm_proxy_url(raw: &str) -> anyhow::Result<reqwest::Url> {\n    let url = reqwest::Url::parse(raw.trim()).map_err(|_| anyhow::anyhow!(\"Base URL 格式无效\"))?;\n    if url.scheme() != \"https\" {\n        anyhow::bail!(\"Base URL 必须使用 HTTPS\");\n    }\n    if !url.username().is_empty() || url.password().is_some() {\n        anyhow::bail!(\"Base URL 不得包含用户名或密码\");\n    }\n    let host = url\n        .host_str()\n        .ok_or_else(|| anyhow::anyhow!(\"Base URL 缺少主机名\"))?;\n    if is_blocked_llm_proxy_host(host) {\n        anyhow::bail!(\"Base URL 不得指向本机或私有网络\");\n    }\n    Ok(url)\n}\n\nfn is_blocked_llm_proxy_host(host: &str) -> bool {\n    let host = host\n        .trim()\n        .trim_start_matches('[')\n        .trim_end_matches(']')\n        .to_lowercase();\n    if host.is_empty()\n        || host == \"localhost\"\n        || host.ends_with(\".localhost\")\n        || host.ends_with(\".local\")\n    {\n        return true;\n    }\n    if let Ok(ip) = std::net::IpAddr::from_str(&host) {","sourceCodeStart":762,"sourceCodeEnd":798,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/f2074595a281bc057525c748175c8eb9805b0673/crates/codex-plus-core/src/routes.rs#L762-L798","documentation":"Thrown by validate_llm_proxy_url when the URL's host is in the blocked set — loopback, private-network, or link-local addresses (is_blocked_llm_proxy_host). This is an SSRF guard keeping the bridge proxy from reaching the local machine or internal network; the offending input is the payload url whose host resolves to a blocked address, and the check runs after scheme/credential validation.","triggerScenarios":"Thrown at crates/codex-plus-core/src/routes.rs:780 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["使用公网可达的 LLM 服务地址","不要用 localhost、127.0.0.1、内网 IP 或 *.local 域名"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"f2074595a281bc057525c748175c8eb9805b0673","analyzedAt":"2026-08-23T12:52:24.489Z","contentChangedAt":"2026-08-23T12:52:24.489Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}