{"record":{"id":"da8cdf19ba3c999f","repo":"santifer/career-ops","slug":"rippling-url-must-use-https-url","errorCode":null,"errorMessage":"rippling: URL must use HTTPS: ${url}","messagePattern":"rippling: URL must use HTTPS: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/rippling.mjs","lineNumber":56,"sourceCode":"  const segment = parsed.pathname.split('/').filter(Boolean)[0] || '';\n  if (!SLUG_RE.test(segment)) return null;\n  return segment;\n}\n\n/** Build the board API URL for a validated slug. */\nfunction apiUrlForSlug(slug) {\n  return `${API_BASE}/${encodeURIComponent(slug)}/jobs`;\n}\n\n/** @param {string} url */\nfunction assertRipplingApiUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`rippling: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`rippling: URL must use HTTPS: ${url}`);\n  if (parsed.hostname !== API_HOST) {\n    throw new Error(`rippling: untrusted hostname \"${parsed.hostname}\" — must be ${API_HOST}`);\n  }\n  return url;\n}\n\n/** @type {Provider} */\nexport default {\n  id: 'rippling',\n\n  detect(entry) {\n    const slug = resolveSlug(entry);\n    return slug ? { url: apiUrlForSlug(slug) } : null;\n  },\n\n  async fetch(entry, ctx) {\n    const slug = resolveSlug(entry);\n    if (!slug) throw new Error(`rippling: cannot derive API URL for ${entry.name}`);","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/providers/rippling.mjs#L38-L74","documentation":"assertRipplingApiUrl rejects any rippling API URL whose protocol is not https:. This enforces encrypted transport and blocks non-HTTP schemes from reaching the fetch layer, complementing the hostname pin to the Rippling API host.","triggerScenarios":"Supplying a URL like http://api.rippling.com/... or any parsed non-https scheme (file:, ftp:) to the rippling provider — typically from a config entry or URL builder that didn't force HTTPS.","commonSituations":"Local development overrides using http://localhost proxies, legacy config with http://, or string concatenation that swapped the scheme.","solutions":["Switch the URL to https:// (e.g. https://api.rippling.com/...).","Fix any URL-building code to hardcode the https scheme.","If testing against a local HTTP mock, mock at the fetch layer instead of changing the validated URL."],"exampleFix":"// before\nconst apiUrl = `http://${API_HOST}/jobs`;\n// after\nconst apiUrl = `https://${API_HOST}/jobs`;","handlingStrategy":"validation","validationCode":"const isHttps = (u) => { try { return new URL(u).protocol === 'https:'; } catch { return false; } };\nif (!isHttps(entry.url)) console.warn(`${entry.name}: upgrade to https://`);","typeGuard":"const isHttpsUrl = (u) => { try { return new URL(u).protocol === 'https:'; } catch { return false; } };","tryCatchPattern":"try { await provider.fetch(entry, ctx); } catch (e) { if (e.message.includes('must use HTTPS')) { console.warn(`Use https:// for ${entry.name}`); return null; } throw e; }","preventionTips":["Hardcode the https scheme in URL builders.","Config-lint for http:// values.","Use https-only mocks in tests."],"tags":["url-validation","https","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"}