{"record":{"id":"423b84803f4f258e","repo":"santifer/career-ops","slug":"eightfold-url-must-use-https-url","errorCode":null,"errorMessage":"eightfold: URL must use HTTPS: ${url}","messagePattern":"eightfold: URL must use HTTPS: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"providers/eightfold.mjs","lineNumber":71,"sourceCode":"// Eightfold's edge rate-limits bursts, and a 616-job board is 62 requests.\nconst INTER_PAGE_DELAY_MS = 250;\n\nconst RETRY_POLICY = { retries: 3, baseDelayMs: 500, maxDelayMs: 8_000 };\n\n/**\n * SSRF guard — every request URL passes through here before it is fetched.\n *\n * @param {string} url\n * @returns {string} the same URL, when it is a trusted Eightfold endpoint.\n */\nfunction assertEightfoldUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`eightfold: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`eightfold: URL must use HTTPS: ${url}`);\n  if (!EIGHTFOLD_HOST_RE.test(parsed.hostname)) {\n    throw new Error(`eightfold: untrusted hostname \"${parsed.hostname}\" — must match *.eightfold.ai`);\n  }\n  return url;\n}\n\n/** @param {number} ms @param {any} ctx */\nfunction sleep(ms, ctx) {\n  if (typeof ctx?.sleep === 'function') return ctx.sleep(ms);\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Eightfold reports timestamps as epoch SECONDS (`t_create`, `t_update`), not\n * the ISO strings every other provider gets. Converted here; anything\n * non-finite or non-positive is dropped rather than guessed at.\n *\n * @param {unknown} value","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/providers/eightfold.mjs#L53-L89","documentation":"This is the second check in assertEightfoldUrl(), the Eightfold provider's SSRF guard: after the URL parses successfully, its protocol must be exactly 'https:'. Any http:, ftp:, or other scheme throws. HTTPS is required because the provider calls a zero-auth JSON API and must not send requests (or leak paths/tenants) over plaintext.","triggerScenarios":"assertEightfoldUrl receives a syntactically valid URL whose parsed.protocol is not 'https:' — typically an http:// link such as http://bayer.eightfold.ai/careers, or a protocol-relative/custom scheme that the URL constructor still parses.","commonSituations":"A portals.yml entry copy-pasted from a browser's insecure-rewrite of the URL; an internal proxy or mirror URL written with http://; a config generator emitting http by default; someone pointing the entry at a local/testing endpoint.","solutions":["Change the scheme to https:// in the entry's api:/careers_url value — Eightfold tenants are all served over HTTPS.","If you were pointing at a local mock/test endpoint, use an https test harness or inject a fetch stub rather than an http URL, since the guard rejects it by design.","Confirm after fixing that the hostname still matches <tenant>.eightfold.ai, otherwise the next guard (untrusted hostname) throws instead.","Run `new URL(value).protocol` in Node to verify the scheme before saving the config."],"exampleFix":"// before (portals.yml)\n- name: bayer\n  api: http://bayer.eightfold.ai/careers\n// after\n- name: bayer\n  api: https://bayer.eightfold.ai/careers","handlingStrategy":"validation","validationCode":"const u = new URL(entry.api || entry.careers_url);\nif (u.protocol !== 'https:') throw new Error(`entry ${entry.name}: use https:// — provider rejects ${u.protocol}// URLs`);","typeGuard":"function isHttpsUrl(v) {\n  if (typeof v !== 'string') return false;\n  try { return new URL(v).protocol === 'https:'; } catch { return false; }\n}","tryCatchPattern":"try {\n  await provider.fetch(entry, ctx);\n} catch (e) {\n  if (e.message.startsWith('eightfold: URL must use HTTPS:')) {\n    // deterministic config issue — rewrite http: to https: and continue; no retry loop\n    const fixed = e.message.split(': ').pop().replace(/^http:/, 'https:');\n    console.error(`Rewrite entry to ${fixed}`);\n  } else throw e;\n}","preventionTips":["Standardize on https:// for every careers_url/api value in portals.yml.","Add a config lint that rejects non-https portal URLs.","Remember Eightfold tenants are all HTTPS-hosted; http mirrors or proxies are never valid inputs.","After fixing the scheme, also confirm the host matches <tenant>.eightfold.ai to pass the next guard."],"tags":["url","https","validation","security"],"backgroundTag":"invalid-url","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}