google-gemini/gemini-cli · error · OAuthSecurityError

Invalid OAuth endpoint protocol "${parsed.protocol}". Only H

Error message

Invalid OAuth endpoint protocol "${parsed.protocol}". Only HTTPS (and HTTP for local development) is supported.

What it means

The OAuth endpoint URL parsed successfully but its protocol is neither http: nor https:. The library only permits HTTP(S) for OAuth endpoints, so schemes like ftp:, file:, ws:, or javascript: are rejected before any network activity. This is an SSRF/abuse guard as much as a validation check.

Source

Thrown at packages/core/src/mcp/oauth-utils.ts:89

      throw new OAuthSecurityError(
        `Failed to resolve relative OAuth URL "${urlStr}" against base "${options.baseUri}": ${getErrorMessage(e)}`,
      );
    }
  }

  let parsed: URL;
  try {
    parsed = new URL(resolvedUrl);
  } catch (e) {
    throw new OAuthSecurityError(
      `Invalid OAuth endpoint URL "${resolvedUrl}": ${getErrorMessage(e)}`,
    );
  }

  const isHttp = parsed.protocol === 'http:';
  const isHttps = parsed.protocol === 'https:';
  if (!isHttp && !isHttps) {
    throw new OAuthSecurityError(
      `Invalid OAuth endpoint protocol "${parsed.protocol}". Only HTTPS (and HTTP for local development) is supported.`,
    );
  }

  const hostname = sanitizeHostname(parsed.hostname);
  const isLoopback = isLoopbackHost(hostname);

  if (isHttp && (!options?.allowLoopback || !isLoopback)) {
    throw new OAuthSecurityError(
      `Insecure HTTP OAuth endpoint "${resolvedUrl}" is not allowed. OAuth endpoints must use HTTPS unless connecting to localhost.`,
    );
  }

  if (options?.expectedOrigin) {
    let expected: string;
    try {
      expected = new URL(options.expectedOrigin).origin;
    } catch {

View on GitHub (pinned to 3c311beac2)

Solutions

  1. Change the endpoint URL to use https:// (or http:// only for local loopback development)
  2. Audit where the URL string is built — often a scheme variable or template placeholder is wrong
  3. If the value came from server-discovered metadata, the remote server is advertising a broken endpoint; fix it server-side or override the endpoint in configuration

Example fix

// before
await validateOAuthEndpointUrl(`${proto}://auth.example.com/authorize`); // proto === 'ws'

// after
await validateOAuthEndpointUrl(`https://auth.example.com/authorize`);
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED = new Set(['http:', 'https:']);
function hasAllowedScheme(v: string): boolean {
  try { return ALLOWED.has(new URL(v).protocol); } catch { return false; }
}

if (!hasAllowedScheme(endpoint)) throw new Error(`Refusing non-HTTP(S) endpoint: ${endpoint}`);

Type guard

function isHttpSchemeUrl(v: string): v is `${'http'|'https'}://${string}` {
  try { const u = new URL(v); return u.protocol === 'http:' || u.protocol === 'https:'; } catch { return false; }
}

Try / catch

try {
  await validateOAuthEndpointUrl(endpoint);
} catch (e) {
  if (e instanceof OAuthSecurityError && e.message.includes('Invalid OAuth endpoint protocol')) {
    // the scheme is wrong (ftp/ws/file/...); rebuild the URL with https://
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing URLs such as 'file:///etc/passwd', 'ftp://host/authorize', 'ws://host/oauth', or any URL whose scheme is not http/https to validateOAuthEndpointUrl.

Common situations: Mistyped or injected configuration values; dynamically constructed URLs where the scheme variable defaults to something unexpected; server metadata advertising an endpoint with a non-HTTP scheme; test fixtures using file:// or data:// URLs.

Related errors


AI-assisted analysis of google-gemini/gemini-cli@3c311beac2 (2026-08-27). Data as JSON: /api/errors/9e1d55d88d7eed0b. Report an issue: GitHub.