{"record":{"id":"9a446fdff0794c3c","repo":"jackwener/OpenCLI","slug":"label-must-point-to-linkedin-com","errorCode":null,"errorMessage":"${label} must point to linkedin.com","messagePattern":"(.+?) must point to linkedin\\.com","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/linkedin/shared.js","lineNumber":100,"sourceCode":"  return /linkedin\\.com\\/(?:login|checkpoint|authwall|uas)/i.test(text)\n    || /\\b(sign in|log in|join linkedin|captcha|verification required)\\b/i.test(text)\n    || /(请登录|登录领英|安全验证)/.test(text);\n}\n\nexport function assertSafeLinkedinUrl(value, label, fallbackPath = '/') {\n  const raw = normalizeWhitespace(value || `https://www.linkedin.com${fallbackPath}`);\n  let parsed;\n  try {\n    parsed = new URL(raw, 'https://www.linkedin.com');\n  } catch {\n    throw new ArgumentError(`${label} must be a LinkedIn URL`);\n  }\n  const host = parsed.hostname.toLowerCase();\n  if (parsed.protocol !== 'https:' || parsed.username || parsed.password || parsed.port) {\n    throw new ArgumentError(`${label} must be an https LinkedIn URL without credentials or port`);\n  }\n  if (host !== 'linkedin.com' && host !== 'www.linkedin.com') {\n    throw new ArgumentError(`${label} must point to linkedin.com`);\n  }\n  return parsed.toString();\n}\n\nexport function requireStringArg(args, key, label = key) {\n  const value = normalizeWhitespace(args?.[key]);\n  if (!value) throw new ArgumentError(`${label} is required`);\n  return value;\n}\n\nexport function parseLimit(value, fallback, max) {\n  if (value === undefined || value === null || value === '') return fallback;\n  const parsed = Number(value);\n  if (!Number.isInteger(parsed) || parsed < 1 || parsed > max) {\n    throw new ArgumentError(`--limit must be an integer between 1 and ${max}`);\n  }\n  return parsed;\n}","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linkedin/shared.js#L82-L118","documentation":"assertSafeLinkedinUrl validates that a caller-supplied LinkedIn URL is safe to use. After requiring an https URL with no embedded credentials or port, it checks the hostname and throws ArgumentError when the host is not linkedin.com or www.linkedin.com. This prevents misuse by ensuring only LinkedIn's canonical domains are accepted.","triggerScenarios":"Calling assertSafeLinkedinUrl (directly or via the 'url' command) with a URL whose hostname is not linkedin.com or www.linkedin.com, e.g. 'https://linkedi.com/in/x', 'https://linkedin.evil.com', a short link like 'https://lnkd.in/abc', or an IP/other-domain host.","commonSituations":"Users pasting shortened LinkedIn share links (lnkd.in), mirror domains, locale subdomains like 'fr.linkedin.com', or typos in the hostname.","solutions":["Use the canonical https://www.linkedin.com/... form of the URL (expand any short links first).","Remove any username:password credentials, non-https scheme, or explicit port from the URL.","If you have a locale subdomain (e.g. fr.linkedin.com), switch to www.linkedin.com.","Verify the URL with `new URL(...)` and check hostname equals 'linkedin.com' or 'www.linkedin.com' before calling."],"exampleFix":"// before\nawait url({ url: 'https://lnkd.in/eXaMpLe' });\n// after\nawait url({ url: 'https://www.linkedin.com/in/some-profile/' });","handlingStrategy":"validation","validationCode":"function isSafeLinkedinUrl(u) {\n  try {\n    const parsed = new URL(u);\n    return parsed.protocol === 'https:' && !parsed.username && !parsed.password && !parsed.port &&\n      (parsed.hostname === 'linkedin.com' || parsed.hostname === 'www.linkedin.com');\n  } catch { return false; }\n}\nif (!isSafeLinkedinUrl(myUrl)) throw new Error('Provide an https www.linkedin.com URL');","typeGuard":"function isLinkedInHostUrl(v) {\n  if (typeof v !== 'string') return false;\n  try {\n    const h = new URL(v).hostname.toLowerCase();\n    return h === 'linkedin.com' || h === 'www.linkedin.com';\n  } catch { return false; }\n}","tryCatchPattern":"try {\n  await url({ url: myUrl });\n} catch (e) {\n  if (e instanceof ArgumentError && /must point to linkedin\\.com/.test(e.message)) {\n    console.error('Use a canonical https://www.linkedin.com/... URL (expand short links).');\n  } else throw e;\n}","preventionTips":["Always use https://www.linkedin.com/... URLs; expand lnkd.in short links first.","Never embed credentials or ports in the URL.","Strip locale subdomains (fr.linkedin.com) down to www.linkedin.com.","Pre-validate hostnames with the URL constructor before invoking the CLI."],"tags":["argument-validation","url-validation","linkedin"],"backgroundTag":"invalid-url-host","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}