{"record":{"id":"b911bb488cb8aa90","repo":"Hmbown/CodeWhale","slug":"codewhale-web-is-loopback-only-and-must-bind-to-12","errorCode":null,"errorMessage":"Codewhale web is loopback-only and must bind to 127.0.0.1","messagePattern":"Codewhale web is loopback-only and must bind to 127\\.0\\.0\\.1","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/lib.rs","lineNumber":2260,"sourceCode":"                let workspace = cli.workspace.clone().unwrap_or_else(|| {\n                    std::env::current_dir().unwrap_or_else(|_| PathBuf::from(\".\"))\n                });\n                let http_selected = validate_serve_mode_selection(\n                    args.mcp,\n                    args.http,\n                    args.mobile,\n                    args.web,\n                    args.acp,\n                )?;\n                if args.mcp {\n                    tokio::task::block_in_place(|| mcp_server::run_mcp_server(workspace))\n                } else if http_selected {\n                    let (config, config_profile) =\n                        load_config_from_cli_with_effective_profile(&cli)?;\n                    let cors_origins = resolve_cors_origins(&config, &args.cors_origin);\n                    let bind_host = resolve_serve_bind_host(args.mobile, args.host);\n                    if args.web && bind_host.host != \"127.0.0.1\" {\n                        bail!(\"Codewhale web is loopback-only and must bind to 127.0.0.1\");\n                    }\n                    if bind_host.mobile_rebound_to_lan {\n                        println!(\n                            \"WARNING: --mobile is binding to 0.0.0.0 so LAN devices can reach the mobile control page. Use --host 127.0.0.1 to keep mobile loopback-only.\"\n                        );\n                    }\n                    runtime_api::run_http_server(\n                        config,\n                        workspace,\n                        std::sync::Arc::clone(&plugin_discovery),\n                        runtime_api::RuntimeApiOptions {\n                            host: bind_host.host,\n                            port: args.port,\n                            workers: args.workers.clamp(1, 8),\n                            cors_origins,\n                            auth_token: args.auth_token,\n                            insecure_no_auth: args.insecure_no_auth,\n                            mobile: args.mobile,","sourceCodeStart":2242,"sourceCodeEnd":2278,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/lib.rs#L2242-L2278","documentation":"For `codewhale serve --web`, the bind host produced by resolve_serve_bind_host(args.mobile, args.host) must be exactly the string 127.0.0.1. Web mode is loopback-only by design — it serves the web surface without the auth hardening required for wider exposure — so the check is a literal comparison and anything else (0.0.0.0, a LAN IP, even `localhost`) is rejected before the HTTP server starts.","triggerScenarios":"`codewhale serve --web --host 0.0.0.0`; `--web --host <lan-ip>` to share the UI; `--web --host localhost` (fails the literal comparison); docker/launcher presets that default --host to 0.0.0.0 for all modes.","commonSituations":"Trying to expose the web UI to a team or another machine; container port-forward setups; muscle memory from --mobile (which warns and rebinds to 0.0.0.0) applied to --web (which hard-fails).","solutions":["Run `codewhale serve --web` with no --host (loopback default) or pass `--host 127.0.0.1` explicitly","Reach a loopback web UI from another device via an SSH tunnel instead of widening the bind","If LAN reachability is the actual requirement, use --mobile, which is built for that and prints its LAN warning"],"exampleFix":"# before\ncodewhale serve --web --host 0.0.0.0\n\n# after\ncodewhale serve --web                     # loopback-only\nssh -L 8080:127.0.0.1:8080 user@host       # remote access via tunnel","handlingStrategy":"validation","validationCode":"# Web mode must stay loopback; assert before launch\nif $WEB && [ \"${HOST:-127.0.0.1}\" != '127.0.0.1' ]; then\n  echo '--web requires --host 127.0.0.1 (loopback-only)'; exit 2\nfi","typeGuard":"fn web_bind_allowed(web: bool, host: &str) -> bool {\n    !web || host == \"127.0.0.1\"\n}","tryCatchPattern":null,"preventionTips":["Never template --host 0.0.0.0 into shared serve launchers","Use --mobile when LAN reachability is the goal; keep --web loopback","Use literal 127.0.0.1, not 'localhost', when overriding --host for --web"],"tags":["serve","web","security","bind-address"],"backgroundTag":"bind-address-rejected","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}