{"record":{"id":"de2c369fdfaa06a1","repo":"DIYgod/RSSHub","slug":"account-should-not-contain-or-path-component","errorCode":null,"errorMessage":"Account should not contain \"://\" or path components","messagePattern":"Account should not contain \"://\" or path components","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/rss3/index.ts","lineNumber":128,"sourceCode":"                {\n                    value: 'transaction',\n                    label: 'transaction',\n                },\n                {\n                    value: 'unknown',\n                    label: 'unknown',\n                },\n            ],\n        },\n    },\n};\n\nasync function handler(ctx) {\n    const { account, network, tag } = ctx.req.param();\n\n    // Check if account contains \"://\" or \"/\"\n    if (account.includes('://') || account.includes('/')) {\n        throw new Error('Account should not contain \"://\" or path components');\n    }\n\n    const { data } = await ofetch(\n        `https://gi.rss3.io/decentralized/${account}?${new URLSearchParams({\n            limit: '20',\n            ...(network && network !== 'all' && { network }),\n            ...(tag && tag !== 'all' && { tag }),\n        })}`\n    );\n\n    return {\n        title: `${account} activities`,\n        link: 'https://rss3.io',\n        item: data.map((item) => {\n            const content = renderItemActionToHTML(camelcaseKeys(item.actions));\n\n            const description = `New ${item.tag} ${item.type} action on ${item.network}<br /><br />From: ${item.from}<br/>To: ${item.to}`;\n            return {","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/rss3/index.ts#L110-L146","documentation":"The RSS3 route takes an `:account` path parameter that is interpolated directly into `https://gi.rss3.io/decentralized/${account}?...`. To prevent path/host injection (a crafted account like `evil.com/x` would redirect the request to a different host) the handler rejects any value containing `://` or `/`. This is a security boundary, not a usability check.","triggerScenarios":"A request like /rss3/https%3A%2F%2Fevil.com/x/ethereum or /rss3/foo/bar where the account segment itself contains a slash or scheme separator. The guard throws before the ofetch call.","commonSituations":"URL-encoded slashes leaking into the account segment; user pastes a full profile URL into the account slot; misconfigured reverse proxy does not collapse path segments.","solutions":["Pass only the bare account identifier (the RSS3 handle/EVM address), not a URL. Example: /rss3/vitalik.eth/ethereum.","URL-decode the input before routing if your client double-encodes slashes.","If you genuinely need a path-style account, this route does not support it — file an upstream feature request instead of bypassing the guard."],"exampleFix":"// before\n/rsshub/rss3/https%3A%2F%2Fmy.eth/ethereum\n\n// after\n/rsshub/rss3/my.eth/ethereum","handlingStrategy":"validation","validationCode":"const account = ctx.req.param('account');\nif (account.includes('://') || account.includes('/')) {\n    return ctx.body('Account must be a bare identifier, not a URL or path.', 400);\n}","typeGuard":"const isBareAccount = (v: unknown): v is string =>\n    typeof v === 'string' && !v.includes('://') && !v.includes('/');","tryCatchPattern":null,"preventionTips":["Strip leading `https://` client-side before routing.","URL-encode account identifiers consistently.","Treat this guard as a security boundary — do not attempt to relax it."],"tags":["security","injection-guard","path-parameter"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}