DIYgod/RSSHub · warning · Error
非法域名!
Error message
非法域名!
What it means
Thrown by the maccms (MacCMS aggregator) route when the :domain path parameter is not in the hardcoded allowlist Set at the bottom of the file (moduzy.net, hw8.live, 360zy.com, etc.). The Chinese message means 'illegal domain!'. This is a security/control measure: the route proxies /api.php/provide/vod from the supplied domain, so only vetted collection sites are allowed.
Source
Thrown at lib/routes/maccms/index.tsx:91
type: '类别ID,不同采集站点有不同的类别规则和ID,默认为 0,代表全部类别',
size: '每次获取的数据条数,上限 100 条,默认 30 条',
},
name: '最新资源',
maintainers: ['hualiong'],
description: `::: tip
每个采集站提供的影视类别 ID 是不同的,即参数中的 \`type\` 是不同的。**可以先访问一次站点提供的采集接口,然后从返回结果中的 \`class\` 字段中的 \`type_id\`获取相应的类别 ID**
:::
| 站名 | 域名 | 站名 | 域名 | 站名 | 域名 |
| ------------------- | ------------------------------------------------ | ---------------- | -------------------------------------------------- | -------------- | ----------------------------------------------- |
| 魔都资源网 | [moduzy.net](https://moduzy.net) | 华为吧影视资源站 | [hw8.live](https://hw8.live) | 360 资源站 | [360zy.com](https://360zy.com) |
| jkun 爱坤联盟资源网 | [ikunzyapi.com](https://ikunzyapi.com) | 奥斯卡资源站 | [aosikazy.com](https://aosikazy.com) | 飞速资源采集网 | [www.feisuzyapi.com](http://www.feisuzyapi.com) |
| 森林资源网 | [slapibf.com](https://slapibf.com) | 天空资源采集网 | [api.tiankongapi.com](https://api.tiankongapi.com) | 百度云资源 | [api.apibdzy.com](https://api.apibdzy.com) |
| 红牛资源站 | [www.hongniuzy2.com](https://www.hongniuzy2.com) | 乐视资源网 | [leshiapi.com](https://leshiapi.com) | 暴风资源 | [bfzyapi.com](https://bfzyapi.com) |`,
handler: async (ctx) => {
const { domain, type = '0', size = '30' } = ctx.req.param();
if (!list.has(domain)) {
throw new Error('非法域名!');
}
const res = await ofetch<Result>(`https://${domain}/api.php/provide/vod`, {
parseResponse: JSON.parse,
query: { ac: 'detail', t: type, pagesize: Number.parseInt(size) > 100 ? 100 : size },
});
const items: DataItem[] = res.list.map((each) => ({
title: each.vod_name,
image: each.vod_pic,
link: `https://${domain}/vod/${each.vod_id}/`,
guid: each.vod_play_url?.match(/https:\/\/.+?\.m3u8/g)?.at(-1),
pubDate: timezone(parseDate(each.vod_time, 'YYYY-MM-DD HH:mm:ss'), 8),
category: [each.type_name, ...each.vod_class!.split(',')],
description: render(each, `https://${domain}/vod/${each.vod_id}/`) + each.vod_content,
}));
return {View on GitHub (pinned to bed535e087)
Solutions
- Use one of the documented allowlisted domains (see the table in the route description).
- If you self-host and trust a new collection site, add its exact hostname string to the list Set at the end of lib/routes/maccms/index.tsx.
- Ensure the domain has no protocol prefix, trailing slash, or port — match the exact string format in the Set.
- Normalize input (strip protocol/www.) before the check if you want more lenient matching, but weigh the SSRF implications.
Example fix
// before
const { domain, type = '0', size = '30' } = ctx.req.param();
if (!list.has(domain)) throw new Error('非法域名!');
// after — strip protocol/www and give a helpful message
const { domain: rawDomain, type = '0', size = '30' } = ctx.req.param();
const domain = rawDomain.replace(/^https?:\/\//, '').replace(/^www\./, '').replace(/\/$/, '');
if (!list.has(domain)) {
throw new InvalidParameterError(`Domain '${domain}' is not allowed. Supported: ${[...list].join(', ')}`);
} Defensive patterns
Strategy: validation
Validate before calling
const list = new Set(['moduzy.net', 'hw8.live', /* ... */]);
const { domain: rawDomain } = ctx.req.param();
const domain = rawDomain.replace(/^https?:\/\//, '').replace(/^www\./, '').replace(/\/$/, '').toLowerCase();
if (!list.has(domain)) {
throw new InvalidParameterError(`Domain '${domain}' not allowed. Supported: ${[...list].join(', ')}`);
} Type guard
function isAllowedMaccmsDomain(d: string, allow: Set<string>): boolean {
const normalized = d.replace(/^https?:\/\//, '').replace(/^www\./, '').replace(/\/$/, '').toLowerCase();
return allow.has(normalized);
} Prevention
- Normalize the domain (strip protocol, www, trailing slash, lowercase) before the allowlist check.
- Derive the route's documentation table from the same Set to avoid drift.
- Throw InvalidParameterError (not generic Error) for unsupported domains so callers can distinguish bad input.
- Weigh SSRF risk before adding new domains or enabling fuzzy matching.
When it happens
Trigger: Calling /maccms/example.com/... where example.com is not in the allowlist. Passing a domain with a trailing slash, port, protocol prefix, or www. that differs from the allowlist entry (e.g. 'www.moduzy.net' when the list has 'moduzy.net'). Passing a subdomain variant.
Common situations: User wants to add a new collection site but it is not in the allowlist. User includes 'https://' or a port. A previously-working domain was removed from the list. The user passes a domain that redirects to a different hostname.
Related errors
- Bad timeRange range. See <a href="https://docs.rsshub.app/ro
- Bad parameter. See <a href="https://docs.rsshub.app/routes/g
- Invalid city
- Invalid channel name
- This category does not exist. Please refer to the documentat
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/ad4ced55b3d91826.
Report an issue: GitHub.