{"record":{"id":"1afc66045236c545","repo":"jackwener/OpenCLI","slug":"expected-a-trusted-https-bilibili-com-video-url-wi","errorCode":null,"errorMessage":"Expected a trusted HTTPS bilibili.com video URL without credentials or a custom port","messagePattern":"Expected a trusted HTTPS bilibili\\.com video URL without credentials or a custom port","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/bilibili/utils.js","lineNumber":27,"sourceCode":"\n/**\n * Parse one exact, case-sensitive BVID or a trusted bilibili.com video URL.\n * Unlike the legacy short-link resolver, this is synchronous and never treats\n * malformed input as a b23.tv network lookup.\n */\nexport function parseBvidOrVideoUrl(value) {\n    const raw = String(value ?? '').trim();\n    if (EXACT_BVID_RE.test(raw)) return raw;\n\n    let parsed;\n    try {\n        parsed = new URL(raw);\n    }\n    catch {\n        throw new ArgumentError('Expected an exact BVID or bilibili.com video URL, for example BV1xx411c7mD');\n    }\n    if (!VIDEO_HOSTS.has(parsed.hostname) || parsed.protocol !== 'https:' || parsed.username || parsed.password || parsed.port) {\n        throw new ArgumentError('Expected a trusted HTTPS bilibili.com video URL without credentials or a custom port');\n    }\n    const match = parsed.pathname.match(/^\\/video\\/(BV[0-9A-Za-z]{10})\\/?$/);\n    if (!match) {\n        throw new ArgumentError('Bilibili video URL did not contain an exact case-sensitive BVID');\n    }\n    return match[1];\n}\n/**\n * Resolve Bilibili short URL / short code to BV ID.\n * Supports: BV1MV9NBtENN, XYzsqGa, b23.tv/XYzsqGa, https://b23.tv/XYzsqGa\n */\nexport function resolveBvid(input) {\n    const trimmed = String(input).trim();\n    if (/^BV[A-Za-z0-9]+$/i.test(trimmed)) {\n        return Promise.resolve(trimmed);\n    }\n    try {\n        const parsed = new URL(trimmed);","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/bilibili/utils.js#L9-L45","documentation":"parseBvidOrVideoUrl validates that the parsed URL uses https, its hostname is in VIDEO_HOSTS (bilibili.com, www.bilibili.com, m.bilibili.com), and contains no username, password, or port. Any violation throws this ArgumentError. The strictness prevents SSRF-style tricks and untrusted hosts from being treated as bilibili video URLs.","triggerScenarios":"Calling bvid/parseBvidOrVideoUrl with http:// (not https) URLs, other domains (e.g. b23.tv, spoofed look-alike hosts like bilibili.com.evil.com), URLs with embedded credentials (https://user:pass@bilibili.com/...), or an explicit port (https://bilibili.com:8443/video/...).","commonSituations":"Copying an http link from an old bookmark; using a short-link domain b23.tv with this strict parser; test fixtures using localhost:port URLs; proxy URLs that inject credentials.","solutions":["Use the canonical https://www.bilibili.com/video/<BVID>/ form","Resolve b23.tv short links to the full URL first (or use resolveBvid)","Strip any credentials or port from the URL","Only pass URLs whose hostname is exactly bilibili.com, www.bilibili.com, or m.bilibili.com"],"exampleFix":"// before\nparseBvidOrVideoUrl('http://bilibili.com:8080/video/BV1xx411c7mD/');\n// after\nparseBvidOrVideoUrl('https://www.bilibili.com/video/BV1xx411c7mD/');","handlingStrategy":"validation","validationCode":"function isTrustedBilibiliVideoUrl(v) {\n  try {\n    const u = new URL(String(v));\n    return u.protocol === 'https:'\n      && ['bilibili.com','www.bilibili.com','m.bilibili.com'].includes(u.hostname)\n      && !u.username && !u.password && !u.port;\n  } catch { return false; }\n}","typeGuard":"function isHttpsNoCredsUrl(v) {\n  if (!(v instanceof URL)) return false;\n  return v.protocol === 'https:' && !v.username && !v.password && !v.port;\n}","tryCatchPattern":"try {\n  const bvid = parseBvidOrVideoUrl(url);\n} catch (err) {\n  if (err instanceof ArgumentError && /trusted HTTPS/.test(err.message)) {\n    console.error(`Untrusted URL form: ${url}. Use https://www.bilibili.com/video/<BVID>/`);\n  } else throw err;\n}","preventionTips":["Canonicalize links to https://www.bilibili.com/video/<BVID>/ before processing","Resolve b23.tv redirects to the final bilibili.com URL first","Reject URLs from user input that contain '@' or ':' after the host (credentials/port)","Whitelist hostnames exactly; never use suffix matching (bilibili.com.evil.com)"],"tags":["argument-validation","security","url-parsing","bilibili"],"backgroundTag":"untrusted-url-host","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}