koala73/worldmonitor · error · RssProxyPolicyError
Redirect to disallowed domain
Error message
Redirect to disallowed domain
What it means
Thrown by assertAllowedRedirect() in the RSS proxy when a redirect response's Location header points to a hostname not in the domain allowlist (isAllowedDomain). This is the second security guard after the protocol check — it prevents the proxy from following redirects to arbitrary (potentially malicious or internal) domains. The www-normalization applied to the initial domain check is also applied here so canonical apex-to-www redirects are not rejected. The error is an RssProxyPolicyError with HTTP status 403.
Source
Thrown at api/rss-proxy.js:85
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);
}
// Handle CORS preflight
if (req.method === 'OPTIONS') {
return new Response(null, { status: 204, headers: corsHeaders });
}
if (req.method !== 'GET') {
return jsonResponse({ error: 'Method not allowed' }, 405, corsHeaders);
}
View on GitHub (pinned to ffec79ac33)
Solutions
- Add the redirect target hostname to the allowlist (isAllowedDomain / ALLOWED_RSS_DOMAINS) if it is a legitimate CDN or mirror of the original feed.
- Contact the feed provider to confirm the new redirect target is legitimate before allowlisting.
- If the redirect is unexpected/suspicious, do NOT add it — investigate whether the feed was compromised.
- Use the Railway relay path for the original domain if the direct redirect chain is problematic (relay-only domains skip direct fetch).
Defensive patterns
Strategy: try-catch
Validate before calling
// Before adding a feed, verify its redirect chain stays within allowed domains
const ALLOWED_DOMAINS = getAllowlist(); // mirror of isAllowedDomain
function isRedirectSafe(location, currentUrl) {
try {
const url = new URL(location, currentUrl);
return (url.protocol === 'http:' || url.protocol === 'https:')
&& ALLOWED_DOMAINS.has(wwwNormalize(url.hostname));
} catch { return false; }
} Type guard
function isRssProxyPolicyError(e: unknown): e is { status: number } & Error {
return e instanceof Error && (e as any).name === 'RssProxyPolicyError'
&& e.message === 'Redirect to disallowed domain';
} Try / catch
try {
const feed = await fetch('/api/rss-proxy?url=' + encodeURIComponent(feedUrl));
} catch (e) {
if (isRssProxyPolicyError(e)) {
// The feed redirected to an un-allowlisted domain
// Either add the redirect target to the allowlist or use the Railway relay
logRedirectIssue(feedUrl);
} else throw e;
} Prevention
- Audit feed redirect targets periodically and add legitimate CDN/mirror domains to the allowlist.
- Use www-normalization when checking hostnames so apex<->www redirects are not false positives.
- Consider adding chronically-redirect-heavy feeds to RELAY_ONLY_DOMAINS to bypass the direct redirect checks.
When it happens
Trigger: An RSS feed URL that is itself allowed (passes the initial check) returns a 301/302/303/307/308 redirect to a hostname that is NOT in the allowlist. For example: a feed at feeds.allowed.com redirects to cdn.disallowed.net/feed.xml. The www-normalization means www.allowed.com and allowed.com are treated equivalently, but a genuinely different domain is blocked.
Common situations: A feed source changed its CDN or redirect target to a new domain not yet in the allowlist; a feed was compromised or misconfigured to redirect to an unexpected domain; a legitimately allowed feed moved hosts and the allowlist was not updated.
Related errors
- URL protocol not allowed
- Too many redirects
- Railway relay unavailable for relay-only domain: ${hostname}
- payload_too_large
- Redis not configured
AI-assisted analysis of koala73/worldmonitor@ffec79ac33 (2026-08-12).
Data as JSON: /api/errors/a68f5a2d0f830383.
Report an issue: GitHub.