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

The BT之家 (btzj) route lets a caller override the mirror domain via the `?domain=` query string. Because letting a user steer RSSHub to an arbitrary host is an SSRF risk, RSSHub gates this behind an allowlist (`allowDomain` = 2btjia.com, 88btbtt.com, btbtt15.com, btbtt20.com) plus a global feature flag `config.feature.allow_user_supply_unsafe_domain`. A ConfigNotFoundError is thrown only when the supplied hostname is NOT in the allowlist AND the flag is disabled.

Source

Thrown at lib/routes/btzj/index.tsx:84

| 求助                 | 音轨字幕             |
| -------------------- | -------------------- |
| forum-index-fid-1187 | forum-index-fid-1191 |

::: tip
BT 之家的域名会变更,本路由以 \`https://www.btbtt20.com\` 为默认域名,若该域名无法访问,可以通过在路由后方加上 \`?domain=<域名>\` 指定路由访问的域名。如指定域名为 \`https://www.btbtt15.com\`,则在 \`/btzj\` 后加上 \`?domain=btbtt15.com\` 即可,此时路由为 [\`/btzj?domain=btbtt15.com\`](https://rsshub.app/btzj?domain=btbtt15.com)

如果加入了分类参数,直接在分类参数后加入 \`?domain=<域名>\` 即可。如指定分类 [剧集](https://www.btbtt20.com/forum-index-fid-950.htm) \`https://www.btbtt20.com/forum-index-fid-950.htm\` 并指定域名为 \`https://www.btbtt15.com\`,即在 \`/btzj/forum-index-fid-950\` 后加上 \`?domain=btbtt15.com\`,此时路由为 [\`/btzj/forum-index-fid-950?domain=btbtt15.com\`](https://rsshub.app/btzj/forum-index-fid-950?domain=btbtt15.com)

目前,你可以选择的域名有 \`btbtt10-20.com\` 共 10 个,或 \`88btbbt.com\`,该站也提供了专用网址查询工具。详见 [此贴](https://www.btbtt20.com/thread-index-fid-2-tid-4550191.htm)
:::`,
};

async function handler(ctx) {
    let category = ctx.req.param('category') ?? '';
    let domain = ctx.req.query('domain') ?? 'btbtt15.com';
    if (!config.feature.allow_user_supply_unsafe_domain && !allowDomain.has(new URL(`http://${domain}/`).hostname)) {
        throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
    }

    if (category === 'base') {
        category = '';
        domain = '88btbtt.com';
    } else if (category === 'govern') {
        category = '';
        domain = '2btjia.com';
    }

    const rootUrl = `https://www.${domain}`;
    const currentUrl = `${rootUrl}${category ? `/${category}.htm` : ''}`;

    const response = await got({
        method: 'get',
        url: currentUrl,
    });

View on GitHub (pinned to bed535e087)

Solutions

  1. Use one of the allowlisted domains: btbtt15.com (default), btbtt20.com, 88btbtt.com, or 2btjia.com.
  2. If you self-host, set the env var ALLOW_USER_SUPPLY_UNSAFE_DOMAIN=true and restart RSSHub.
  3. Omit `?domain=` entirely to fall back to the default btbtt15.com.
  4. If a legitimate new btbtt mirror is needed on a public instance, open a PR adding it to the `allowDomain` Set at lib/routes/btzj/index.tsx:12.

Example fix

// before
//   /btzj?domain=mybtreddit.com
// after
//   /btzj?domain=btbtt15.com   (or omit ?domain=)
Defensive patterns

Strategy: validation

Validate before calling

import { config } from '@/config';
const allowDomain = new Set(['2btjia.com', '88btbtt.com', 'btbtt15.com', 'btbtt20.com']);
function isDomainAllowed(domain: string): boolean {
  return config.feature.allow_user_supply_unsafe_domain || allowDomain.has(new URL(`http://${domain}/`).hostname);
}
// call before building the route URL
if (!isDomainAllowed(domain)) { /* surface a 4xx to the user instead of crashing */ }

Prevention

When it happens

Trigger: Requesting `/btzj?domain=<x>` (or `/btzj/<category>?domain=<x>`) where `new URL('http://<x>/').hostname` is not one of the four allowlisted hosts, on an instance where ALLOW_USER_SUPPLY_UNSAFE_DOMAIN is unset/false.

Common situations: Public rsshub.app users copying a domain from the btbtt domain-finder thread that isn't hardcoded; self-hosters who did not set ALLOW_USER_SUPPLY_UNSAFE_DOMAIN; supplying a bare TLD or a URL that normalises to a non-allowlisted hostname.

Related errors


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