{"record":{"id":"c7c1cf3c6a0c43e4","repo":"santifer/career-ops","slug":"yourator-url-must-use-https-url","errorCode":null,"errorMessage":"yourator: URL must use HTTPS: ${url}","messagePattern":"yourator: URL must use HTTPS: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/yourator.mjs","lineNumber":83,"sourceCode":"\nconst SITE_ORIGIN = 'https://www.yourator.co';\nconst FEED_BASE = `${SITE_ORIGIN}/api/v4/jobs`;\nconst TRUSTED_HOST = 'www.yourator.co';\n// Safety bound only — the loop stops on payload.hasMore. The live board was 88\n// pages on 2026-08-18; this leaves room to grow without silently truncating.\nconst DEFAULT_MAX_PAGES = 120;\nconst MAX_PAGES_CAP = 500;\nconst PAGE_DELAY_MS = 200;\n\n/** @param {string} url */\nfunction assertYouratorUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`yourator: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`yourator: URL must use HTTPS: ${url}`);\n  if (parsed.hostname !== TRUSTED_HOST) {\n    throw new Error(`yourator: untrusted hostname \"${parsed.hostname}\" — must be ${TRUSTED_HOST}`);\n  }\n  return url;\n}\n\n/** Resolve the page cap: a positive integer `max_pages` on the entry, capped. */\nfunction resolveMaxPages(entry) {\n  const v = entry?.max_pages;\n  if (Number.isInteger(v) && v > 0) return Math.min(v, MAX_PAGES_CAP);\n  return DEFAULT_MAX_PAGES;\n}\n\n/**\n * Canonical URL for a posting — Source Indexing Policy rule 2, \"the shortest\n * verifiable path to the employer the source exposes\".\n *\n * Prefers `thirdPartyUrl` (the employer's own ATS page), with the board's","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/santifer/career-ops/blob/1696bec4d021768e7359f9aad6b329cba883da20/providers/yourator.mjs#L65-L101","documentation":"The Yourator provider only fetches its public jobs API from a hard-pinned HTTPS host. Before any network request, assertYouratorUrl parses the configured careers_url and rejects it if the protocol is not https:. This is a deliberate security guard: the provider will not send requests over plaintext HTTP where responses could be tampered with. It fails fast at configuration time rather than at fetch time.","triggerScenarios":"assertYouratorUrl is called with a URL string whose parsed.protocol is not 'https:' — e.g. a job_boards entry with careers_url: http://www.yourator.co/jobs, or programmatic calls passing http:// or ftp:// URLs, or a URL like HTTPS:// (any scheme other than the exact lowercase 'https:').","commonSituations":"Copy-pasting the board URL from a browser where a redirect or extension downgraded it to http; hand-writing config with http:// out of habit; a URL string built by concatenation that accidentally lost the 's'; testing against a local mirror served over http.","solutions":["Change the scheme to https:// in the careers_url of the yourator job_boards entry (e.g. https://www.yourator.co/jobs).","Verify the URL parses with `new URL(url)` and that url.protocol === 'https:' before passing it to the provider.","If you control the endpoint, serve it over HTTPS; the provider will never fall back to HTTP by design."],"exampleFix":"// before\ncareers_url: http://www.yourator.co/jobs\n\n// after\ncareers_url: https://www.yourator.co/jobs","handlingStrategy":"validation","validationCode":"import { URL } from 'node:url';\nexport function isHttpsUrl(u) {\n  try { return new URL(u).protocol === 'https:'; } catch { return false; }\n}\nif (!isHttpsUrl(careersUrl)) careersUrl = careersUrl.replace(/^http:/, 'https:');","typeGuard":"function assertHttps(u) {\n  const p = new URL(u); // throws on unparseable\n  if (p.protocol !== 'https:') throw new TypeError(`expected https:, got ${p.protocol}`);\n  return p;\n}","tryCatchPattern":"try {\n  runYouratorScan(entry);\n} catch (e) {\n  if (e.message.includes('URL must use HTTPS')) {\n    entry.careers_url = entry.careers_url.replace(/^http:\\/\\//i, 'https://');\n    runYouratorScan(entry);\n  } else throw e;\n}","preventionTips":["Always write https:// in job_boards careers_url entries; grep config for 'http://' before running scans.","Normalize scheme in your config loader (http→https) for known-trusted hosts.","Add a lint/test that parses every careers_url in config and asserts protocol and parsability."],"tags":["security","configuration","https","url-validation"],"backgroundTag":"insecure-url-scheme-rejected","analyzedSha":"1696bec4d021768e7359f9aad6b329cba883da20","analyzedAt":"2026-09-01T19:19:23.111Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}