{"record":{"id":"bf5902fd36cbb024","repo":"Hmbown/CodeWhale","slug":"refusing-insecure-base-url-display-base-url","errorCode":null,"errorMessage":"Refusing insecure base URL '{display_base_url}'.\n\nLoopback hosts (localhost, 127.0.0.1, [::1]) are auto-allowed.\nFor other trusted local hosts (LAN, llama.cpp on a private IP, etc.)\nset the env var `{ALLOW_INSECURE_HTTP_ENV}=1` in the shell that runs codewhale and re-run.\n\nExample: `{ALLOW_INSECURE_HTTP_ENV}=1 codewhale` (note the underscores).","messagePattern":"Refusing insecure base URL '(.+?)'\\.\n\nLoopback hosts \\(localhost, 127\\.0\\.0\\.1, \\[::1\\]\\) are auto-allowed\\.\nFor other trusted local hosts \\(LAN, llama\\.cpp on a private IP, etc\\.\\)\nset the env var `(.+?)=1` in the shell that runs codewhale and re-run\\.\n\nExample: `(.+?)=1 codewhale` \\(note the underscores\\)\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/client.rs","lineNumber":673,"sourceCode":"    {\n        return Ok(());\n    }\n\n    if base_url.starts_with(\"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 base_url.starts_with(\"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 other trusted local hosts (LAN, llama.cpp on a private IP, etc.)\\n\\\n             set the env var `{ALLOW_INSECURE_HTTP_ENV}=1` in the shell that runs codewhale and re-run.\\n\\\n             \\n\\\n             Example: `{ALLOW_INSECURE_HTTP_ENV}=1 codewhale` (note the underscores).\",\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\npub(crate) fn redact_url_for_display(url: &str) -> String {\n    let Ok(mut parsed) = reqwest::Url::parse(url) else {\n        return url.to_string();","sourceCodeStart":655,"sourceCodeEnd":691,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/client.rs#L655-L691","documentation":"`validate_base_url_security` in the HTTP client refuses plain-HTTP base URLs to prevent API keys being sent unencrypted. Only `http://localhost`, `http://127.0.0.1`, and `http://[::1]` are auto-allowed; any other `http://` host is rejected unless the env var `CODEWHALE_ALLOW_INSECURE_HTTP` (legacy alias `DEEPSEEK_ALLOW_INSECURE_HTTP`) is set to `1` or `true` in the process that runs codewhale, in which case a warning is logged and the URL is accepted.","triggerScenarios":"Setting a provider `base_url` like `http://192.168.1.10:11434` (Ollama on LAN), `http://10.0.0.5:8080` (llama.cpp on a private IP), or `http://myserver.local:8000` (vLLM/LM Studio on another machine) without the env var set, or with it set to some other value like `yes`/`on` (only `1` and case-insensitive `true` count), or exported in a different shell than the one launching codewhale.","commonSituations":"Running a local LLM server on a NAS/second box reachable only over LAN HTTP; using an HTTP-terminating proxy; after the DEEPSEEK->CODEWHALE rename the old env var still works as an alias, but a half-remembered name like `CODEWHALE_ALLOW_INSECURE` (missing `_HTTP`) does not.","solutions":["Set `CODEWHALE_ALLOW_INSECURE_HTTP=1` in the same shell that starts codewhale: `CODEWHALE_ALLOW_INSECURE_HTTP=1 codewhale` (underscores, value exactly 1 or true).","Prefer reconfiguring the server for HTTPS (reverse proxy with TLS) and keep the `https://` base_url.","Or bind the server to loopback and use `http://localhost:PORT` / `http://127.0.0.1:PORT`, which needs no env var.","If the env var seems set but still fails, confirm it is exported into codewhale's process (`env | grep ALLOW_INSECURE`) and spelled `CODEWHALE_ALLOW_INSECURE_HTTP`."],"exampleFix":"# before (fails at startup)\nexport base_url='http://192.168.1.10:11434'\ncodewhale\n# after\nCODEWHALE_ALLOW_INSECURE_HTTP=1 codewhale","handlingStrategy":"validation","validationCode":"// Check before constructing/starting the client.\nfn base_url_allowed(base_url: &str) -> bool {\n    base_url.starts_with(\"https://\")\n        || base_url.starts_with(\"http://localhost\")\n        || base_url.starts_with(\"http://127.0.0.1\")\n        || base_url.starts_with(\"http://[::1]\")\n        || (base_url.starts_with(\"http://\")\n            && std::env::var(\"CODEWHALE_ALLOW_INSECURE_HTTP\")\n                .or_else(|_| std::env::var(\"DEEPSEEK_ALLOW_INSECURE_HTTP\"))\n                .is_ok_and(|v| v == \"1\" || v.eq_ignore_ascii_case(\"true\")))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Put `export CODEWHALE_ALLOW_INSECURE_HTTP=1` in the same shell profile/launcher that starts codewhale so it is always in the process env.","Prefer TLS (reverse proxy with a certificate) or loopback binding for local model servers.","Document the exact value constraints early: only `1` or `true` (case-insensitive) are accepted; `yes`/`on` silently fail."],"tags":["security","configuration","base-url","http","environment","network"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}