{"record":{"id":"a2f04d3f19776134","repo":"santifer/career-ops","slug":"comeet-invalid-url-redacttoken-url","errorCode":null,"errorMessage":"comeet: invalid URL: ${redactToken(url)}","messagePattern":"comeet: invalid URL: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"providers/comeet.mjs","lineNumber":34,"sourceCode":"/** @param {unknown} raw */\nfunction isComeetApiUrl(raw) {\n  if (typeof raw !== 'string' || !raw) return false;\n  let parsed;\n  try {\n    parsed = new URL(raw);\n  } catch {\n    return false;\n  }\n  return parsed.protocol === 'https:' && parsed.hostname === COMEET_API_HOST && parsed.pathname.startsWith('/careers-api/');\n}\n\n/** @param {string} url */\nfunction assertComeetUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`comeet: invalid URL: ${redactToken(url)}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`comeet: URL must use HTTPS: ${redactToken(url)}`);\n  if (parsed.hostname !== COMEET_API_HOST)\n    throw new Error(`comeet: untrusted hostname \"${parsed.hostname}\" — must be ${COMEET_API_HOST}`);\n  if (!parsed.pathname.startsWith('/careers-api/'))\n    throw new Error(`comeet: URL path must be the careers-api endpoint: ${redactToken(url)}`);\n  return url;\n}\n\n// Redact the per-tenant ?token= so neither the (informational, possibly-logged)\n// DetectHit url nor a thrown validation error carries the secret. Best-effort:\n// falls back to a regex strip when the value can't be parsed as a URL.\nfunction redactToken(url) {\n  try {\n    const parsed = new URL(url);\n    if (parsed.searchParams.has('token')) parsed.searchParams.set('token', 'REDACTED');\n    return parsed.href;\n  } catch {","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/providers/comeet.mjs#L16-L52","documentation":"assertComeetUrl validates that a URL is a syntactically valid Comeet careers-api URL before the provider fetches it. The first check is parseability: new URL(url) throws for malformed strings, and assertComeetUrl converts that into a labeled error (with the per-tenant ?token= redacted) so failures are attributable to the right portal entry.","triggerScenarios":"resolveApiUrl passed a value that failed the isComeetApiUrl guard for a non-format reason — practically, fetch() receives an entry whose api/careers_url is a malformed string (missing scheme, spaces, unescaped characters) that somehow bypassed the typeof/URL pre-checks, or assertComeetUrl is called directly with user input that isn't a URL.","commonSituations":"Pasting a Comeet careers page URL with a typo (missing 'https://', stray space or newline copied from a document); storing the URL with surrounding quotes in YAML; hand-editing portals.yml and breaking the URL.","solutions":["Inspect the entry's api/careers_url value in portals.yml and fix the malformed URL string","Ensure the URL includes the scheme: https://www.comeet.co/careers-api/2.0/company/<uid>/positions?token=<token>","Trim whitespace/quotes when loading the config (the provider only trims in the collage provider; comeet's isComeetApiUrl rejects whitespace-padded strings)","Validate with new URL(url) locally before committing the config"],"exampleFix":"// before (portals.yml)\n- name: Acme\n  provider: comeet\n  api: www.comeet.co/careers-api/2.0/company/acme/positions?token=abc\n// after\n- name: Acme\n  provider: comeet\n  api: https://www.comeet.co/careers-api/2.0/company/acme/positions?token=abc","handlingStrategy":"validation","validationCode":"function isParseableUrl(raw) {\n  if (typeof raw !== 'string' || !raw.trim()) return false;\n  try { new URL(raw.trim()); return true; } catch { return false; }\n}\nif (!isParseableUrl(entry.api)) throw new Error(`entry ${entry.name}: api is not a valid URL`);","typeGuard":"function isUrlString(raw) {\n  if (typeof raw !== 'string') return false;\n  try { new URL(raw); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  const url = assertComeetUrl(entry.api);\n} catch (err) {\n  if (String(err.message).includes('invalid URL')) {\n    logger.error({entry: entry.name}, 'comeet api value is not a parseable URL — check scheme, quotes, whitespace');\n  } else throw err;\n}","preventionTips":["Always include the https:// scheme when pasting Comeet API URLs into portals.yml","Trim copied URLs; watch for hidden whitespace/newlines and YAML quoting artifacts","Validate the whole portals.yml with a URL-schema check in CI before running scans","Use the token-redacted error message as-is; don't re-log the raw URL (it carries a secret)"],"tags":["config","url","validation","provider"],"backgroundTag":"invalid-url-format","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"}