{"record":{"id":"33e70187e11e8055","repo":"santifer/career-ops","slug":"jobvite-url-must-use-https-url","errorCode":null,"errorMessage":"jobvite: URL must use HTTPS: ${url}","messagePattern":"jobvite: URL must use HTTPS: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/jobvite.mjs","lineNumber":100,"sourceCode":"// 1.88 MB for 236 jobs in ~11s. That overshoots the shared 10s default in\n// _http.mjs by a second, which aborted the whole tenant and reported it as a\n// network failure. Sized to absorb a genuinely big tenant on a slow link; the\n// board page (a normal HTML document) keeps the default.\nconst FEED_TIMEOUT_MS = 45_000;\n\n/**\n * Pin a URL to the two known Jobvite hosts over HTTPS.\n * @param {string} url\n */\nfunction assertJobviteHost(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`jobvite: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:')\n    throw new Error(`jobvite: URL must use HTTPS: ${url}`);\n  if (!ALLOWED_HOSTS.has(parsed.hostname))\n    throw new Error(`jobvite: untrusted hostname \"${parsed.hostname}\" — must be ${BOARD_HOST} or ${FEED_HOST}`);\n  return url;\n}\n\n// NaN-safe Date.parse → epoch ms.\n/** @param {string} value */\nfunction toEpochMs(value) {\n  if (!value) return undefined;\n  const parsed = Date.parse(value);\n  return Number.isNaN(parsed) ? undefined : parsed;\n}\n\n/**\n * The vanity slug from a Jobvite careers URL, or null.\n * Only used to build the board URL for eId discovery.\n *\n * @param {import('./_types.js').PortalEntry} entry","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/providers/jobvite.mjs#L82-L118","documentation":"Thrown by assertJobviteHost() when a Jobvite URL parses successfully but uses any protocol other than https: (e.g. http:, ftp:). This is a hard SSRF guard — the provider pins both the Jobvite board host and the XML feed host to HTTPS and refuses to fetch anything else, so an accidental or maliciously injected cleartext URL never reaches the network.","triggerScenarios":"A careers_url or api URL in a portals.yml job_boards entry that starts with http:// instead of https://; an entry edited by hand that dropped the scheme; or a malformed input where the protocol substring got mangled. The check runs inside assertJobviteHost(), which is called on every URL the provider builds (boardUrl, feedUrl) before any fetch.","commonSituations":"Copy-pasting a Jobvite careers URL from a browser that auto-stripped the scheme; a config file where a legacy entry predates the HTTPS-only policy; a redirect target that was constructed without upgrading the scheme.","solutions":["Edit the offending portals.yml entry and change the protocol to https:// (e.g. http://jobs.jobvite.com/acme → https://jobs.jobvite.com/acme).","If the error references a built URL (not your config), verify the entry's company_eid or api field is well-formed, since buildBoardFetchUrl/buildFeedUrl derive the host from constants and the only variable input is the slug/eid.","Re-run the scan to confirm the corrected entry no longer trips the guard."],"exampleFix":"// before (portals.yml)\njob_boards:\n  acme:\n    provider: jobvite\n    careers_url: http://jobs.jobvite.com/acme\n\n// after\njob_boards:\n  acme:\n    provider: jobvite\n    careers_url: https://jobs.jobvite.com/acme","handlingStrategy":"validation","validationCode":"function isHttpsUrl(url) {\n  try {\n    return new URL(url).protocol === 'https:';\n  } catch {\n    return false;\n  }\n}\n// before passing entry.careers_url to the jobvite provider:\nif (!isHttpsUrl(entry.careers_url)) {\n  throw new Error(`config: ${entry.name} careers_url must be https://`);\n}","typeGuard":"/** @param {string} url @returns {boolean} */\nfunction isJobviteHttpsUrl(url) {\n  try {\n    const p = new URL(url);\n    return p.protocol === 'https:' && /(^|\\.)jobvite\\.com$/i.test(p.hostname);\n  } catch {\n    return false;\n  }\n}","tryCatchPattern":null,"preventionTips":["Validate all job_boards URLs in a config-lint pass before running a scan.","Normalize careers_url entries to https:// at config load time and warn on any http:// input.","Treat the SSRF guards as authoritative — do not wrap provider calls in try/catch that swallows them."],"tags":["jobvite","ssrf-guard","url-validation","config"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}