Hmbown/CodeWhale · error · anyhow::Error
reviewed plugin MCP endpoint has an unsafe origin
Error message
reviewed plugin MCP endpoint has an unsafe origin
What it means
reviewed_remote_origin accepts only https endpoints, or http when the host is exactly `localhost` or a loopback IP literal, with a host present and no userinfo (crates/tui/src/mcp.rs:1006-1019); the resulting origin is pinned as the approved origin that later redirects must stay on. This error means the reviewed plugin's endpoint fell outside those rules - an unsafe origin for a trusted plugin.
Source
Thrown at crates/tui/src/mcp.rs:1002
.context("open reviewed launch file without links, hard links, or write/delete sharing")
}
#[cfg(all(not(unix), not(windows)))]
fn open_reviewed_launch_file(path: &Path) -> Result<fs::File> {
fs::File::open(path).context("open reviewed launch file")
}
fn reviewed_remote_endpoint_identity(endpoint: &str) -> Result<(String, String)> {
let endpoint =
reqwest::Url::parse(endpoint).context("reviewed plugin MCP endpoint is invalid")?;
if !endpoint.username().is_empty() || endpoint.password().is_some() {
anyhow::bail!("reviewed plugin MCP endpoint must not contain user information");
}
if endpoint.query().is_some() || endpoint.fragment().is_some() {
anyhow::bail!("reviewed plugin MCP endpoint must not contain a query or fragment");
}
let origin = reviewed_remote_origin(&endpoint)
.ok_or_else(|| anyhow::anyhow!("reviewed plugin MCP endpoint has an unsafe origin"))?;
Ok((endpoint.to_string(), origin))
}
fn reviewed_remote_origin(endpoint: &reqwest::Url) -> Option<String> {
if !endpoint.username().is_empty() || endpoint.password().is_some() {
return None;
}
let host = endpoint.host_str()?;
let allowed_scheme = endpoint.scheme() == "https"
|| (endpoint.scheme() == "http"
&& (host.eq_ignore_ascii_case("localhost")
|| host
.trim_matches(['[', ']'])
.parse::<std::net::IpAddr>()
.is_ok_and(|address| address.is_loopback())));
allowed_scheme.then(|| endpoint.origin().ascii_serialization())
}
View on GitHub (pinned to 8880682c63)
Solutions
- Serve the endpoint over HTTPS (put a TLS reverse proxy in front if the server itself cannot do TLS).
- For local servers keep http but address it as http://localhost:PORT or http://127.0.0.1:PORT - loopback IP literals are allowed.
- Fix scheme typos, then re-trust the plugin so the new origin is pinned.
Example fix
# before url = "http://192.168.1.20:8931/mcp" # after: TLS via reverse proxy, or loopback literal for local servers url = "https://mcp.home.example.com/mcp" # (local alternative: url = "http://127.0.0.1:8931/mcp")
Defensive patterns
Strategy: validation
Validate before calling
fn reviewed_origin_ok(endpoint: &str) -> bool {
let Ok(u) = reqwest::Url::parse(endpoint) else { return false };
if !u.username().is_empty() || u.password().is_some() { return false; }
let Some(host) = u.host_str() else { return false; };
u.scheme() == "https"
|| (u.scheme() == "http"
&& (host.eq_ignore_ascii_case("localhost")
|| host.trim_matches(['[', ']'])
.parse::<std::net::IpAddr>()
.is_ok_and(|a| a.is_loopback())))
} Prevention
- Serve reviewed plugin endpoints over HTTPS; plain http only on localhost/loopback literals.
- Avoid ws:// and other schemes in plugin endpoints.
- Re-trust after any endpoint change so the new origin is pinned.
When it happens
Trigger: Endpoints like http://192.168.1.10:8080/mcp (plain http on a non-loopback host), ws:// or other schemes, or a URL with no host component.
Common situations: LAN/home-lab MCP servers over plain http; scheme typos (ws:// copied from examples); endpoints pasted without the host.
Related errors
- reviewed plugin MCP endpoint must not contain user informati
- fleet alert URL from {name} must use https
- reviewed plugin stage could not be opened for launch
- reviewed plugin stdio cwd escaped its staged root
- Refusing to {operation} MCP server '{server_name}' from plug
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/d1d3606739a85c00.
Report an issue: GitHub.