koala73/worldmonitor · error · RssProxyPolicyError

URL protocol not allowed

Error message

URL protocol not allowed

What it means

Thrown by assertHttpProtocol() in the RSS proxy edge function when a feed URL's protocol is neither http: nor https: (e.g. ftp:, javascript:, file:, data:). This is a security guard preventing the proxy from being used as an SSRF vector. The error is an RssProxyPolicyError with HTTP status 400 (the default for the initial URL check).

Source

Thrown at api/rss-proxy.js:75

    }),
  }, timeoutMs);
}

// Allowlist + match predicate live in api/_rss-allowed-domain-match.js
// (shared with scripts/validate-rss-feeds.mjs --ci so the SSRF guard runs
// identically in the Edge handler and the build-time validator).

function isGoogleNewsFeedUrl(feedUrl) {
  try {
    return new URL(feedUrl).hostname === 'news.google.com';
  } catch {
    return false;
  }
}

function assertHttpProtocol(url, message = 'URL protocol not allowed', status = 400) {
  if (url.protocol !== 'http:' && url.protocol !== 'https:') {
    throw new RssProxyPolicyError(message, status);
  }
}

function assertAllowedRedirect(url) {
  assertHttpProtocol(url, 'Redirect protocol not allowed', 403);
  // Apply the same www-normalization as the initial domain check so that
  // canonical redirects (e.g. apex -> www) are not incorrectly rejected when
  // only one form is in the allowlist.
  if (!isAllowedDomain(url.hostname)) {
    throw new RssProxyPolicyError('Redirect to disallowed domain');
  }
}

export default async function handler(req, ctx) {
  const corsHeaders = getCorsHeaders(req, 'GET, OPTIONS');

  if (isDisallowedOrigin(req)) {
    return jsonResponse({ error: 'Origin not allowed' }, 403, corsHeaders);

View on GitHub (pinned to ffec79ac33)

Solutions

  1. Ensure the feed URL uses http:// or https:// — re-encode the url query parameter correctly.
  2. If the URL looks correct, check for hidden characters or encoding issues in the url query parameter (e.g. url=http%3A%2F%2F... vs a raw ftp://).
  3. For redirect-path instances (status 403, message 'Redirect protocol not allowed'), the initial URL was fine but a redirect Location header pointed to a non-HTTP URL — the source needs to fix its redirect.
  4. Validate the URL client-side before calling the proxy.

Example fix

// before
GET /api/rss-proxy?url=ftp://feeds.example.com/news.xml
// after
GET /api/rss-proxy?url=https://feeds.example.com/news.xml
Defensive patterns

Strategy: validation

Validate before calling

// Validate the feed URL protocol before calling the RSS proxy
function isValidFeedUrl(urlStr) {
  try {
    const url = new URL(urlStr);
    return url.protocol === 'http:' || url.protocol === 'https:';
  } catch {
    return false;
  }
}
if (!isValidFeedUrl(feedUrl)) {
  throw new Error(`Feed URL must use http or https protocol: ${feedUrl}`);
}

Type guard

function isRssProxyPolicyError(e: unknown): e is { status: number } & Error {
  return e instanceof Error && (e as any).name === 'RssProxyPolicyError';
}

Prevention

When it happens

Trigger: Calling GET /api/rss-proxy?url=<feedUrl> where the feedUrl parses to a non-HTTP protocol — e.g. url=ftp://feeds.example.com/rss, url=javascript:alert(1), or a malformed URL that the URL constructor parses with an unexpected protocol. Also fires on the redirect path with a different message ('Redirect protocol not allowed', status 403).

Common situations: A feed URL in the source registry or user input that uses a non-standard protocol; an attempted SSRF payload targeting internal protocols (file:///etc/passwd); a copy-paste error introducing a typo in the URL scheme; a feed URL that was valid but got mangled by URL encoding.

Related errors


AI-assisted analysis of koala73/worldmonitor@ffec79ac33 (2026-08-12). Data as JSON: /api/errors/29002455166492ae. Report an issue: GitHub.