Hmbown/CodeWhale · error
Codewhale mobile is loopback-only without TLS or a verified…
Error message
Codewhale mobile is loopback-only without TLS or a verified overlay; bind to 127.0.0.1 or ::1
What it means
Mobile control over the Runtime API is plain HTTP with no TLS or verified overlay, so binding to a non-loopback host would expose it to peers that can observe or replay traffic. This bail enforces loopback binding (127.0.0.1 or ::1) whenever mobile mode is on.
Solutions
- Bind to 127.0.0.1 or ::1
- Reach the runtime from the mobile device via an SSH tunnel or VPN loopback forward
- Use the pairing/overlay mechanism instead of a raw non-loopback bind
Example fix
// before codewhale runtime --mobile --host 0.0.0.0 // after codewhale runtime --mobile --host 127.0.0.1
Defensive patterns
Strategy: validation
Validate before calling
const LOOPBACK: [&str; 2] = ["127.0.0.1", "::1"];
if mobile_enabled && !LOOPBACK.contains(&host.as_str()) { return Err("mobile mode requires a loopback bind".into()); } Prevention
- Bind mobile mode to 127.0.0.1 or ::1 only
- Use tunnels/VPN to reach the runtime from a phone, never a public bind
- Treat mobile HTTP as unencrypted and plan transports accordingly
When it happens
Trigger: Starting the Runtime API with mobile enabled and `is_loopback_bind_host(&options.host)` false — e.g. `--host 0.0.0.0`, an LAN IP, or a hostname resolving off-loopback.
Common situations: Trying to use the mobile app from another device by binding 0.0.0.0; Docker/container defaults binding all interfaces; assuming mobile mode implies a secure transport.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Codewhale web is loopback-only and must bind to 127.0.0.1
- Unauthenticated Runtime access is loopback-only; remove…
- Codewhale web requires Runtime authentication; remove…
- agent action=claim widens an enforced write scope, and the…
- allowlisted read-only executable
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/a69551af29b17487.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/runtime_api.rs:1113
task_manager.shutdown_and_wait().await?;
serve_result
}
/// Mobile control uses plain HTTP only on loopback. It has no TLS or verified
/// overlay transport, so a non-loopback listener would expose the Runtime API
/// to peers that can observe or replay browser traffic.
fn validate_runtime_listener_security(options: &RuntimeApiOptions) -> Result<()> {
if options.port == 0 {
bail!("Port must be > 0");
}
if options.web && options.host != "127.0.0.1" {
bail!("Codewhale web is loopback-only and must bind to 127.0.0.1");
}
if options.web && options.insecure_no_auth {
bail!("Codewhale web requires Runtime authentication; remove --insecure");
}
if options.mobile && !is_loopback_bind_host(&options.host) {
bail!(
"Codewhale mobile is loopback-only without TLS or a verified overlay; bind to 127.0.0.1 or ::1"
);
}
if options.insecure_no_auth && !is_loopback_bind_host(&options.host) {
bail!(
"Unauthenticated Runtime access is loopback-only; remove --insecure or bind to 127.0.0.1 or ::1"
);
}
Ok(())
}
fn is_loopback_bind_host(host: &str) -> bool {
host.parse::<IpAddr>()
.is_ok_and(|address| address.is_loopback())
}
fn runtime_bind_address(host: &str, port: u16) -> Result<SocketAddr> {
let address = match host.parse::<IpAddr>() {View on GitHub (pinned to 73e0f67d83)