{"record":{"id":"e29456069478280c","repo":"DIYgod/RSSHub","slug":"this-rss-is-disabled-unless-allow-user-supply-uns-e29456","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/json.ts","lineNumber":76,"sourceCode":"\n| Parameter     | Value                                                                    |\n| ------------- | ------------------------------------------------------------------------ |\n| \\`url\\`         | \\`https://api.github.com/repos/ginuerzh/gost/releases\\`                    |\n| \\`routeParams\\` | \\`title=Gost releases&itemTitle=tag_name&itemLink=html_url&itemDesc=body\\` |\n\nParsing of \\`routeParams\\` parameter:\n\n| Parameter   | Value           |\n| ----------- | --------------- |\n| \\`title\\`     | \\`Gost releases\\` |\n| \\`itemTitle\\` | \\`tag_name\\`      |\n| \\`itemLink\\`  | \\`html_url\\`      |\n| \\`itemDesc\\`  | \\`body\\`          |`,\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    let rssTitle = routeParams.get('title');\n    if (!rssTitle) {\n        const resp = await got({\n            method: 'get',\n            url: new URL(url).origin,\n        });\n        const $ = load(resp.data);\n        rssTitle = $('title').text();\n    }\n","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/rsshub/transform/json.ts#L58-L94","documentation":"The JSON transformation route mirrors the HTML one: it fetches an arbitrary user-supplied URL and reshapes the JSON into RSS. The same SSRF gate (`config.feature.allow_user_supply_unsafe_domain`) blocks the handler unless the operator has opted in. The check runs before `got({url})` and before routeParams parsing.","triggerScenarios":"A request to /rsshub/transform/json/... on an instance where `ALLOW_USER_SUPPLY_UNSAFE_DOMAIN` is not enabled.","commonSituations":"User tries the transform feature on a public RSSHub instance; self-hosted instance was deployed from default docker-compose without the env var.","solutions":["Enable `ALLOW_USER_SUPPLY_UNSAFE_DOMAIN=true` on your own instance and restart, understanding this opens an SSRF vector — pair it with network policy.","Run a dedicated, firewalled RSSHub just for transform routes if you need them regularly.","Check whether a native route exists for the target API and use it instead."],"exampleFix":"// before\n# config.feature.allow_user_supply_unsafe_domain = false (default)\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 JSON 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":["Enable the flag only on a network-isolated instance.","Prefer route-specific feeds when available.","Audit user-supplied URLs with an allowlist before enabling broadly."],"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"}