CoplayDev/unity-mcp · error · Exception
{context}: refusing to send credentials to an unexpected hos
Error message
{context}: refusing to send credentials to an unexpected host in URL '{url}' (expected https://{allowedHost}). What it means
Thrown by ProviderHttp.RequireHost, a credential-leak guard. Every auth-bearing request URL is routed through it so that a malicious or MITM'd provider response (e.g. a rogue response_url or download URL) cannot redirect the API key to an attacker-controlled host. It requires an absolute https URL whose host exactly equals allowedHost; anything else throws. The message is scrubbed of the key. This is a deliberate security fail-fast, not a bug.
Source
Thrown at MCPForUnity/Editor/Services/AssetGen/Providers/ProviderHttp.cs:26
/// <summary>
/// Shared HTTP-response helpers for provider adapters: read the response text (falling back to
/// a UTF-8 decode of the raw body) and truncate long bodies for inclusion in error messages.
/// </summary>
internal static class ProviderHttp
{
/// <summary>
/// Throw unless <paramref name="url"/> is an absolute https URL whose host is exactly
/// <paramref name="allowedHost"/>. Adapters route every auth-bearing request URL through
/// this so a malicious/MITM'd provider response (e.g. a rogue response_url) can't redirect
/// the API key to an attacker host. The error is scrubbed of the key.
/// </summary>
public static void RequireHost(string url, string allowedHost, string apiKey, string context)
{
if (!Uri.TryCreate(url, UriKind.Absolute, out Uri u)
|| u.Scheme != Uri.UriSchemeHttps
|| !string.Equals(u.Host, allowedHost, StringComparison.OrdinalIgnoreCase))
{
throw new Exception(SecretRedactor.Scrub(
$"{context}: refusing to send credentials to an unexpected host in URL '{url}' (expected https://{allowedHost}).",
apiKey));
}
}
/// <summary>Response text, falling back to a UTF-8 decode of the raw body when Text is empty.</summary>
public static string BodyText(HttpResult res)
{
string text = res?.Text;
if (string.IsNullOrEmpty(text) && res?.Body != null)
text = Encoding.UTF8.GetString(res.Body);
return text;
}
/// <summary>Cap a (possibly null) string at 500 chars for inclusion in an error message.</summary>
public static string Truncate(string s)
{
if (string.IsNullOrEmpty(s)) return string.Empty;View on GitHub (pinned to c21bf496bc)
Solutions
- Do NOT disable or bypass this check — it prevents API-key exfiltration.
- If the host change is legitimate (e.g. a new CDN), update the allowedHost passed to RequireHost for that call site to the new trusted host.
- If unexpected, investigate the upstream response that produced the off-host URL — it may indicate a compromised/MITM endpoint.
- Ensure the URL is absolute https and the host matches exactly (no trailing slash, correct subdomain).
Defensive patterns
Strategy: validation
Validate before calling
// Validate the host yourself before relying on a provider-supplied URL.
static bool IsTrustedHost(string url, string allowed)
=> Uri.TryCreate(url, UriKind.Absolute, out var u)
&& u.Scheme == Uri.UriSchemeHttps
&& string.Equals(u.Host, allowed, StringComparison.OrdinalIgnoreCase); Type guard
static bool IsSafeCredentialUrl(string url, string allowedHost)
=> Uri.TryCreate(url, UriKind.Absolute, out var u)
&& u.Scheme == Uri.UriSchemeHttps
&& u.Host.Equals(allowedHost, StringComparison.OrdinalIgnoreCase); Try / catch
// This is a security fail-fast — do NOT swallow silently. Investigate the source of the URL.
try { ProviderHttp.RequireHost(url, allowedHost, apiKey, ctx); }
catch (Exception) { McpLog.Error($"Blocked credential send to off-host URL: {url}"); throw; } Prevention
- Never bypass RequireHost; update allowedHost to the new trusted CDN host if a provider legitimately moves.
- Treat any off-host URL from a provider response as suspicious until confirmed legitimate.
- Keep endpoint/CDN host constants in one place so a migration is a single edit.
When it happens
Trigger: A provider response embeds a download/redirect URL on a different domain than the expected provider host; a CDN host changed; an endpoint constant was edited to a wrong host; http (non-https) URL; a relative URL passed where absolute was expected.
Common situations: Sketchfab/Meshy moves its asset CDN to a new domain; a developer overrides an endpoint constant; a test stub returns a localhost URL; an attacker-influenced field reaches RequireHost.
Related errors
- image_path must point to a file under the project's Assets f
- CredWrite failed (Win32 {GetLastWin32Error})
- provider returned a disallowed file type '.{ext}'
- Unsafe zip entry rejected: {name}
- Unsafe zip entry escapes destination: {name}
AI-assisted analysis of CoplayDev/unity-mcp@c21bf496bc (2026-08-13).
Data as JSON: /api/errors/0fe2a1873dda80c5.
Report an issue: GitHub.