DIYgod/RSSHub · error · ConfigNotFoundError

This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN

Error message

This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.

What it means

Thrown by the javdb route's ProcessItems as a ConfigNotFoundError when the user-supplied `domain` query parameter is neither in the hardcoded allowDomain set ({javdb.com, javdb571.com, javdb36.com, javdb007.com, javdb521.com}) nor explicitly permitted via the ALLOW_USER_SUPPLY_UNSAFE_DOMAIN feature flag. It is an SSRF-guard: the route builds a Playwright URL from arbitrary user input, so only trusted domains are allowed by default.

Source

Thrown at lib/routes/javdb/utils.ts:17

import { load } from 'cheerio';

import { config } from '@/config';
import ConfigNotFoundError from '@/errors/types/config-not-found';
import type { DataItem } from '@/types';
import cache from '@/utils/cache';
import logger from '@/utils/logger';
import { parseDate } from '@/utils/parse-date';
import { getPlaywrightPage } from '@/utils/playwright';

const allowDomain = new Set(['javdb.com', 'javdb571.com', 'javdb36.com', 'javdb007.com', 'javdb521.com']);

const ProcessItems = async (ctx, currentUrl, title) => {
    const domain = ctx.req.query('domain') ?? 'javdb.com';
    const url = new URL(currentUrl, `https://${domain}`);
    if (!config.feature.allow_user_supply_unsafe_domain && !allowDomain.has(url.hostname)) {
        throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
    }

    const rootUrl = `https://${domain}`;

    const { page, destroy, context } = await getPlaywrightPage(url.href, {
        onBeforeLoad: async (page) => {
            if (config.javdb.session) {
                await page.context().addCookies([
                    {
                        name: '_jdb_session',
                        value: config.javdb.session,
                        domain,
                        path: '/',
                    },
                ]);
            }
            await page.route('**/*', (route) => {
                const request = route.request();

View on GitHub (pinned to bed535e087)

Solutions

  1. Use one of the whitelisted domains, e.g. /javdb?domain=javdb571.com
  2. If you run your own instance and trust the new mirror, add its hostname to allowDomain in lib/routes/javdb/utils.ts:9
  3. Alternatively set ALLOW_USER_SUPPLY_UNSAFE_DOMAIN=true in the instance config (only when you understand the SSRF implications)
  4. Verify the hostname exactly — allowDomain.has uses exact match, so www.javdb.com is rejected even though javdb.com is allowed

Example fix

// before
const allowDomain = new Set(['javdb.com', 'javdb571.com', 'javdb36.com']);
// after — add the mirror you actually use
const allowDomain = new Set(['javdb.com', 'javdb571.com', 'javdb36.com', 'javdb007.com', 'javdb521.com', 'javdb618.com']);
Defensive patterns

Strategy: validation

Validate before calling

import config from '@/utils/config';
const ALLOW_DOMAIN = new Set(['javdb.com', 'javdb571.com', 'javdb36.com', 'javdb007.com', 'javdb521.com']);
function assertAllowedDomain(domain: string | undefined): void {
  const d = domain ?? 'javdb.com';
  const host = new URL(currentUrl, `https://${d}`).hostname;
  if (!config.feature.allow_user_supply_unsafe_domain && !ALLOW_DOMAIN.has(host)) {
    throw new ConfigNotFoundError(`domain '${host}' not allowed`);
  }
}

Type guard

const ALLOW_DOMAIN = new Set(['javdb.com', 'javdb571.com', 'javdb36.com', 'javdb007.com', 'javdb521.com']);
function isAllowedJavdbDomain(domain: string): boolean {
  return ALLOW_DOMAIN.has(domain);
}

Try / catch

// Validate before invoking ProcessItems
if (!isAllowedJavdbDomain(domain) && !config.feature.allow_user_supply_unsafe_domain) {
  return ctx.json({ error: 'domain not allowed' }, 400);
}
try { return await ProcessItems(ctx, currentUrl, title); }
catch (e) {
  if (e instanceof ConfigNotFoundError) { /* user-facing 400 */ }
  throw e;
}

Prevention

When it happens

Trigger: A request like /javdb?domain=evil.example.com (or any domain not in the allow-set) while config.feature.allow_user_supply_unsafe_domain is false/undefined. The new URL constructor accepts it, allowDomain.has() returns false, and the guard fires.

Common situations: Operator points the route at a javdb mirror not yet in the allow-list; self-hosters who have not set ALLOW_USER_SUPPLY_UNSAFE_DOMAIN=true; typos in the domain query param; attempts to abuse the route as an open proxy.

Related errors


AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12). Data as JSON: /api/errors/119cb487397a72d9. Report an issue: GitHub.