{"record":{"id":"47bacb1cb779b7c5","repo":"santifer/career-ops","slug":"arbeitnow-url-must-use-https-url","errorCode":null,"errorMessage":"arbeitnow: URL must use HTTPS: ${url}","messagePattern":"arbeitnow: URL must use HTTPS: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/arbeitnow.mjs","lineNumber":32,"sourceCode":"// override with `max_pages` on the portal entry).\n//\n// Wire in via a `job_boards:` entry with `provider: arbeitnow`.\n\nconst FEED_BASE = 'https://www.arbeitnow.com/api/job-board-api';\nconst TRUSTED_HOST = 'www.arbeitnow.com';\nconst PER_PAGE = 100;\nconst DEFAULT_MAX_PAGES = 3;\nconst MAX_PAGES_CAP = 50;\n\n/** @param {string} url */\nfunction assertArbeitnowUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`arbeitnow: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`arbeitnow: URL must use HTTPS: ${url}`);\n  if (parsed.hostname !== TRUSTED_HOST) {\n    throw new Error(`arbeitnow: 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 * Normalize a single Arbeitnow job. Exported for unit tests.\n *\n * Field mapping → the normalized Job shape:\n *   - title:    `title`, trimmed (items without one are dropped).","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/providers/arbeitnow.mjs#L14-L50","documentation":"Part of arbeitnow's `assertArbeitnowUrl` SSRF guard. After `new URL(url)` parses successfully, the provider rejects any scheme other than `https:`. This enforces transport security and blocks `http://` (and exotic schemes) from being used against the trusted host.","triggerScenarios":"`parsed.protocol !== 'https:'` after a successful parse. Triggered by an `http://www.arbeitnow.com/...` URL, or any other scheme (`ftp:`, `file:`) that resolves to the right host.","commonSituations":"A config value copied from a non-secure source, an environment that downgrades URLs to http, or a local proxy URL left in place of the real endpoint.","solutions":["Prefix the URL with `https://`: use `https://www.arbeitnow.com/api/job-board-api`.","Strip any `http://` override from config/env before it reaches the provider.","If testing locally against a TLS-terminating proxy, point it at an https front door rather than disabling the check."],"exampleFix":"// before\nconst url = 'http://www.arbeitnow.com/api/job-board-api';\n\n// after\nconst url = 'https://www.arbeitnow.com/api/job-board-api';","handlingStrategy":"validation","validationCode":"function ensureHttps(u) {\n  try {\n    if (new URL(u).protocol !== 'https:') throw new Error(`not https: ${u}`);\n    return u;\n  } catch { throw new Error(`arbeitnow: bad URL: ${u}`); }\n}\nconst FEED_BASE = ensureHttps(rawBase);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Normalize config URLs to https at load time.","Reject http:// overrides in env/config with a clear startup error.","Run a config linter that flags non-https provider URLs."],"tags":["arbeitnow","url-validation","https","ssrf"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}