{"record":{"id":"e0b31f56556d82c3","repo":"santifer/career-ops","slug":"pinpoint-url-must-use-https-url","errorCode":null,"errorMessage":"pinpoint: URL must use HTTPS: ${url}","messagePattern":"pinpoint: URL must use HTTPS: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/pinpoint.mjs","lineNumber":32,"sourceCode":"// match on `<safe-slug>.pinpointhq.com` rather than a static allowlist, the\n// same approach as the recruitee provider.\n\n// The tenant label must be a valid DNS label: it may contain hyphens but must\n// not start or end with one (so `acme-.pinpointhq.com` is rejected). The\n// optional trailing group keeps single-character labels (e.g. `a.pinpointhq.com`)\n// valid. detect() and fetch() both route through this constant via\n// resolveApiUrl()/assertPinpointUrl(), so the stricter check applies everywhere.\nconst PINPOINT_HOST_RE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.pinpointhq\\.com$/;\n\n/** @param {string} url */\nfunction assertPinpointUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`pinpoint: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`pinpoint: URL must use HTTPS: ${url}`);\n  if (!PINPOINT_HOST_RE.test(parsed.hostname)) {\n    throw new Error(`pinpoint: untrusted hostname \"${parsed.hostname}\" — must match <slug>.pinpointhq.com`);\n  }\n  return url;\n}\n\nfunction resolveApiUrl(entry) {\n  const raw = typeof entry.careers_url === 'string' ? entry.careers_url : '';\n  if (!raw) return null;\n  let parsed;\n  try {\n    parsed = new URL(raw);\n  } catch {\n    return null;\n  }\n  if (parsed.protocol !== 'https:') return null;\n  if (!PINPOINT_HOST_RE.test(parsed.hostname)) return null;\n  return `https://${parsed.hostname}/postings.json`;","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/providers/pinpoint.mjs#L14-L50","documentation":"assertPinpointUrl enforces HTTPS for every URL it accepts; a URL with any other scheme (http:, ftp:) is rejected with this error. Pinpoint feeds are always served over TLS, so the provider refuses non-https input up front to keep the SSRF guard and transport policy uniform.","triggerScenarios":"Calling code paths through assertPinpointUrl (pinpoint.mjs line 32) with careers_url scheme http:// — e.g. http://acme.pinpointhq.com — or a scheme that parsed to something unexpected from a malformed string.","commonSituations":"Hand-authored config with http://; legacy internal links; snippets copied from docs with http; scripts that build URLs with a hardcoded http scheme.","solutions":["Change the scheme to https:// in the portals.yml careers_url.","Confirm the tenant serves https in a browser (all *.pinpointhq.com tenants do).","Fix any URL-building template to emit https://${host}.","Grep portals.yml for http:// to catch and fix all insecure scheme values at once."],"exampleFix":"// before (portals.yml)\ncareers_url: http://acme.pinpointhq.com\n// after\ncareers_url: https://acme.pinpointhq.com","handlingStrategy":"validation","validationCode":"function isHttpsPinpointUrl(u) {\n  if (typeof u !== 'string') return false;\n  try { return new URL(u).protocol === 'https:'; } catch { return false; }\n}\nif (!isHttpsPinpointUrl(entry.careers_url)) throw new Error(`pinpoint: careers_url for ${entry.name} must use https://`);","typeGuard":"function isHttpsPinpointUrl(u) {\n  if (typeof u !== 'string') return false;\n  try {\n    const parsed = new URL(u);\n    return parsed.protocol === 'https:' && /^[a-z0-9-]+\\.pinpointhq\\.com$/.test(parsed.hostname);\n  } catch { return false; }\n}","tryCatchPattern":"try {\n  await pinpointProvider.fetch(entry, ctx);\n} catch (e) {\n  if (String(e.message).startsWith('pinpoint: URL must use HTTPS')) {\n    logger.warn({ entry: entry.name, url: entry.careers_url }, 'rewrite http:// to https:// in portals.yml');\n    return null;\n  }\n  throw e;\n}","preventionTips":["Never author http:// careers_url values; default to https.","CI-lint portals.yml to reject non-https schemes on any careers_url.","Bulk-fix legacy http links before committing config changes.","Keep URL-builder templates emitting https:// only."],"tags":["https","url-validation","config","pinpoint"],"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"}