Hmbown/CodeWhale · error · anyhow::Error
reviewed plugin MCP endpoint must not contain a query or fra
Error message
reviewed plugin MCP endpoint must not contain a query or fragment
What it means
reviewed_remote_endpoint_identity rejects reviewed-plugin MCP endpoints whose URL contains a query string or fragment (crates/tui/src/mcp.rs:998-1000). Only the origin (scheme+host+port) and path are trusted; query/fragment parts are mutable request details that could carry credentials or bypass the pinned-origin redirect policy, so they are refused outright.
Source
Thrown at crates/tui/src/mcp.rs:999
#[cfg(windows)]
fn open_reviewed_launch_file(path: &Path) -> Result<fs::File> {
crate::plugins::manifest::open_bundle_file(path)
.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())));View on GitHub (pinned to 8880682c63)
Solutions
- Remove everything from '?' onwards and from '#' onwards: declare https://api.example.com/mcp only.
- Move any needed auth material to env_headers or oauth config instead of the URL.
- Re-trust the plugin after the manifest change (/plugin reload, /plugin trust <name> <token>).
Example fix
# before url = "https://mcp.example.com/sse?api_key=secret#prod" # after url = "https://mcp.example.com/sse"
Defensive patterns
Strategy: validation
Validate before calling
fn endpoint_has_query_or_fragment(endpoint: &str) -> bool {
reqwest::Url::parse(endpoint)
.map(|u| u.query().is_some() || u.fragment().is_some())
.unwrap_or(true)
} Prevention
- Declare only scheme://host[:port]/path in plugin endpoints.
- Put auth and routing parameters in headers, not the URL.
- Strip pasted anchors (#...) from documentation URLs before use.
When it happens
Trigger: An endpoint declared as https://api.example.com/mcp?token=abc or https://api.example.com/mcp#section in a reviewed plugin manifest.
Common situations: Providers that hand out connect URLs with API keys in the query string; anchors accidentally pasted from documentation pages.
Related errors
- reviewed plugin MCP endpoint must not contain user informati
- reviewed plugin MCP endpoint has an unsafe origin
- invalid --base-url: ${args.baseUrl}
- --base-url must use http or https
- MCP config path cannot be empty
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/8851929117b33f1f.
Report an issue: GitHub.