{"record":{"id":"a5d0e18061893439","repo":"DIYgod/RSSHub","slug":"this-rss-is-disabled-unless-allow-user-supply-uns-a5d0e1","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":"error_code","errorClass":"ConfigNotFoundError","httpStatus":503,"severity":"warning","filePath":"lib/routes/rsshub/transform/sitemap.ts","lineNumber":38,"sourceCode":"        requirePuppeteer: false,\n        antiCrawler: false,\n        supportBT: false,\n        supportPodcast: false,\n        supportScihub: false,\n    },\n    name: 'Transformation - Sitemap',\n    maintainers: ['flrngel'],\n    description: `Specify options (in the format of query string) in parameter \\`routeParams\\` parameter to extract data from Sitemap. (Follows Sitemap Protocol 0.9)\n\n| Key     | Meaning              | Accepted Values | Default                          |\n| ------- | -------------------- | --------------- | -------------------------------- |\n| \\`title\\` | The title of the RSS | \\`string\\`        | The first \\`<loc>\\` in the sitemap |`,\n    handler,\n};\n\nasync function handler(ctx) {\n    if (!config.feature.allow_user_supply_unsafe_domain) {\n        throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);\n    }\n    const url = ctx.req.param('url');\n    const response = await got({\n        method: 'get',\n        url,\n    });\n\n    const routeParams = new URLSearchParams(ctx.req.param('routeParams'));\n    const $ = load(response.data, { xmlMode: true });\n\n    const rssTitle = routeParams.get('title') || ($('urlset url').length && $('urlset url').first().find('loc').text() ? $('urlset url').first().find('loc').text() : 'Sitemap');\n\n    const urls = $('urlset url').toArray();\n    const items =\n        urls && urls.length\n            ? (urls\n                  .map((item) => {\n                      try {","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/rsshub/transform/sitemap.ts#L20-L56","documentation":"The Sitemap transformation route fetches a user-supplied sitemap URL and converts `<urlset>` entries into RSS items. Identical SSRF gate to the html/json transform routes: requires `config.feature.allow_user_supply_unsafe_domain === true`. Throws before any HTTP call.","triggerScenarios":"A request to /rsshub/transform/sitemap/... on an instance with the flag disabled.","commonSituations":"Public rsshub.app usage; fresh self-hosted deploy; operator removed the flag after a security review.","solutions":["Set `ALLOW_USER_SUPPLY_UNSAFE_DOMAIN=true` on an instance you control, with appropriate network egress controls, and restart.","Use a purpose-built sitemap-to-RSS tool outside RSSHub if you cannot safely enable the flag.","Point users at native routes when the target site has one."],"exampleFix":"// before\n# flag unset\n\n// after\nALLOW_USER_SUPPLY_UNSAFE_DOMAIN=true","handlingStrategy":"validation","validationCode":"if (!config.feature?.allow_user_supply_unsafe_domain) {\n    return ctx.body('Transform sitemap route requires ALLOW_USER_SUPPLY_UNSAFE_DOMAIN=true.', 403);\n}","typeGuard":"const isUnsafeDomainAllowed = (c: typeof config): boolean =>\n    c.feature?.allow_user_supply_unsafe_domain === true;","tryCatchPattern":null,"preventionTips":["Pair the flag with firewall egress rules.","Run transform routes on a separate instance from authenticated routes.","Rotate which instances are publicly reachable."],"tags":["config-missing","security","ssrf-guard"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}