{"record":{"id":"49827fd94a308e27","repo":"Hmbown/CodeWhale","slug":"refusing-insecure-base-url-display-base-url-loopback-hosts-49827f","errorCode":null,"errorMessage":"Refusing insecure base URL '{display_base_url}'.\n\nLoopback hosts (localhost, 127.0.0.1, [::1]) are auto-allowed.\nFor one trusted local provider (LAN, llama.cpp on a private IP, etc.) set\n`allow_insecure_http = true` under its `[providers.<name>]` table in config.toml.\nTo allow it for every provider in this shell instead, set the env var\n`{ALLOW_INSECURE_HTTP_ENV}=1` and re-run.","messagePattern":"Refusing insecure base URL '(.+?)'\\.\n\nLoopback hosts \\(localhost, 127\\.0\\.0\\.1, \\[::1\\]\\) are auto-allowed\\.\nFor one trusted local provider \\(LAN, llama\\.cpp on a private IP, etc\\.\\) set\n`allow_insecure_http = true` under its `\\[providers\\.<name>\\]` table in config\\.toml\\.\nTo allow it for every provider in this shell instead, set the env var\n`(.+?)=1` and re-run\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/client.rs","lineNumber":1112,"sourceCode":"        );\n        return Ok(());\n    }\n\n    if parsed.scheme() == \"http\"\n        && std::env::var(ALLOW_INSECURE_HTTP_ENV)\n            .or_else(|_| std::env::var(LEGACY_ALLOW_INSECURE_HTTP_ENV))\n            .ok()\n            .as_deref()\n            .is_some_and(|v| v == \"1\" || v.eq_ignore_ascii_case(\"true\"))\n    {\n        logging::warn(format!(\n            \"Using insecure HTTP base URL because {ALLOW_INSECURE_HTTP_ENV} is set\"\n        ));\n        return Ok(());\n    }\n\n    if parsed.scheme() == \"http\" {\n        anyhow::bail!(\n            \"Refusing insecure base URL '{display_base_url}'.\\n\\\n             \\n\\\n             Loopback hosts (localhost, 127.0.0.1, [::1]) are auto-allowed.\\n\\\n             For one trusted local provider (LAN, llama.cpp on a private IP, etc.) set\\n\\\n             `allow_insecure_http = true` under its `[providers.<name>]` table in config.toml.\\n\\\n             To allow it for every provider in this shell instead, set the env var\\n\\\n             `{ALLOW_INSECURE_HTTP_ENV}=1` and re-run.\",\n        );\n    }\n\n    anyhow::bail!(\n        \"Refusing base URL '{display_base_url}': only HTTPS (or explicitly allowed HTTP) URLs are supported.\",\n    )\n}\n\n/// Mask credentials in a URL for display.\n///\n/// Delegates to the single shared implementation in","sourceCodeStart":1094,"sourceCodeEnd":1130,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/client.rs#L1094-L1130","documentation":"The HTTP client refuses to connect to a provider whose base URL uses plain http:// on a non-loopback host. Loopback hosts (localhost, 127.0.0.1, [::1]) are auto-allowed; anything else would send prompts and API keys in cleartext, so startup fails with this message explaining the three opt-in mechanisms. It is a deliberate security guard against credential leakage over unencrypted LAN traffic.","triggerScenarios":"Configuring a provider with an http:// base URL pointing at a LAN/private-IP host (e.g. http://192.168.1.50:8080) and starting a session, without any insecure-HTTP opt-in.","commonSituations":"Pointing Codewhale at a local llama.cpp/Ollama/LM Studio instance by its LAN IP; docker/VM setups where the model server is reachable only via a private address; typo-ing https:// as http://.","solutions":["Use https:// for the provider base URL (preferred fix).","Use a loopback host (localhost / 127.0.0.1) with a port-forward or tunnel so the auto-allow applies.","Set `allow_insecure_http = true` under the specific `[providers.<name>]` table in config.toml for that one trusted provider.","Set the ALLOW_INSECURE_HTTP_ENV env var to 1 to allow insecure HTTP for every provider in this shell (broadest, least safe)."],"exampleFix":"// config.toml — before\n[providers.llamacpp]\nbase_url = \"http://192.168.1.50:8080\"\n// after\n[providers.llamacpp]\nbase_url = \"http://192.168.1.50:8080\"\nallow_insecure_http = true","handlingStrategy":"validation","validationCode":"let url = url::Url::parse(&base_url)?;\nlet insecure = url.scheme() == \"http\"\n    && !matches!(url.host_str(), Some(\"localhost\") | Some(h) if h.parse::<std::net::IpAddr>().map(|i| i.is_loopback()).unwrap_or(false));\nif insecure && !provider_allow_insecure_http && std::env::var(\"CODEWHALE_ALLOW_INSECURE_HTTP\") != Ok(\"1\".into()) {\n    // switch to https / loopback, or set the opt-in before startup\n}","typeGuard":null,"tryCatchPattern":"match build_client(&provider) {\n    Ok(c) => c,\n    Err(e) if e.to_string().contains(\"Refusing insecure base URL\") => {\n        eprintln!(\"{e}\"); // the message lists the exact opt-in options\n        std::process::exit(2);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Default provider base URLs to https:// and only use http for loopback hosts.","For LAN model servers, tunnel over SSH (localhost forward) instead of allowing insecure HTTP.","Scope any insecure-HTTP opt-in to a single provider table rather than the global env var.","Double-check scheme typos (http vs https) when configuring local providers."],"tags":["security","http","configuration","network"],"backgroundTag":"invalid-url","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}