{"record":{"id":"400bb003b1bf26ee","repo":"DIYgod/RSSHub","slug":"this-rss-is-disabled-unless-allow-user-supply-uns-400bb0","errorCode":null,"errorMessage":"This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.","messagePattern":"This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'\\.","errorType":"exception","errorClass":"ConfigNotFoundError","httpStatus":503,"severity":"warning","filePath":"lib/routes/misskey/home-timeline.ts","lineNumber":74,"sourceCode":"        },\n    ],\n    name: 'Home Timeline',\n    maintainers: ['HanaokaYuzu'],\n    handler,\n    description: `::: warning\nThis route is only available for self-hosted instances.\n:::`,\n};\n\nasync function handler(ctx) {\n    const access_token = config.misskey.accessToken;\n    if (!access_token) {\n        throw new ConfigNotFoundError('Missing access token for Misskey API. Please set `MISSKEY_ACCESS_TOKEN` environment variable.');\n    }\n\n    const site = ctx.req.param('site');\n    if (!config.feature.allow_user_supply_unsafe_domain && !utils.allowSiteList.includes(site)) {\n        throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);\n    }\n\n    // docs on: https://misskey.io/api-doc#tag/notes/operation/notes___timeline\n    const url = `https://${site}/api/notes/timeline`;\n    const routeParams = querystring.parse(ctx.req.param('routeParams'));\n    const response = await got({\n        method: 'post',\n        url,\n        headers: {\n            Authorization: `Bearer ${access_token}`,\n        },\n        json: {\n            limit: Number(routeParams.limit ?? 10),\n            withFiles: queryToBoolean(routeParams.withFiles ?? false),\n            withRenotes: queryToBoolean(routeParams.withRenotes ?? true),\n            allowPartial: queryToBoolean(routeParams.allowPartial ?? true),\n        },\n    });","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/misskey/home-timeline.ts#L56-L92","documentation":"Thrown as ConfigNotFoundError by the Misskey home-timeline route (the second guard, after the token check). It fires when :site is not in utils.allowSiteList and config.feature.allow_user_supply_unsafe_domain is false — the same SSRF guard as the featured-notes route, but evaluated only after the access token is confirmed present.","triggerScenarios":"A valid MISSKEY_ACCESS_TOKEN is set, but the requested :site is not on the curated allow-list and ALLOW_USER_SUPPLY_UNSAFE_DOMAIN is not enabled. The handler refuses to POST to an arbitrary host.","commonSituations":"Self-hoster correctly set the token for their own Misskey instance but their instance isn't in RSSHub's allow-list; they didn't know about the unsafe-domain toggle.","solutions":["Set ALLOW_USER_SUPPLY_UNSAFE_DOMAIN=true (self-host only, understanding it affects all guarded routes) and restart RSSHub.","Alternatively request an allow-listed instance, or add your instance to utils.allowSiteList if you control RSSHub.","Confirm :site has no trailing slash/path (e.g. use 'misskey.example.com', not 'https://misskey.example.com/')."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const site = ctx.req.param('site');\nif (!config.feature.allow_user_supply_unsafe_domain && !utils.allowSiteList.includes(site)) {\n    throw new ConfigNotFoundError(`Host '${site}' not allowed. Enable ALLOW_USER_SUPPLY_UNSAFE_DOMAIN or use an allow-listed instance.`);\n}","typeGuard":"function isAllowedSite(site: string, allowList: string[], unsafeAllowed: boolean): boolean {\n    return typeof site === 'string' && (allowList.includes(site) || unsafeAllowed);\n}","tryCatchPattern":null,"preventionTips":["Prefer allow-listing a specific instance over enabling the global unsafe-domain flag.","Document the SSRF rationale so operators understand the risk of the toggle.","Normalize :site (strip scheme/slash) before the check to avoid bypass-via-malformation."],"tags":["ssrf-guard","allow-list","missing-config","misskey","unsafe-domain"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}