{"record":{"id":"07c2b10ad85e51b0","repo":"santifer/career-ops","slug":"themuse-invalid-url-url","errorCode":null,"errorMessage":"themuse: invalid URL: ${url}","messagePattern":"themuse: invalid URL: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/themuse.mjs","lineNumber":20,"sourceCode":"/** @typedef {import('./_types.js').Provider} Provider */\n\n// The Muse provider — public, zero-auth JSON jobs feed.\n// Endpoint: https://www.themuse.com/api/public/jobs?page={n}\n// Response shape: { results: [...], page: n, page_count: N }\n// All pages are fetched sequentially and aggregated before normalizing.\n//\n// Wire in via a `job_boards:` entry with `provider: themuse`.\n\nconst FEED_BASE = 'https://www.themuse.com/api/public/jobs';\nconst TRUSTED_HOST = 'www.themuse.com';\n\n/** @param {string} url */\nfunction assertMuseUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`themuse: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`themuse: URL must use HTTPS: ${url}`);\n  if (parsed.hostname !== TRUSTED_HOST) {\n    throw new Error(`themuse: untrusted hostname \"${parsed.hostname}\" — must be ${TRUSTED_HOST}`);\n  }\n  return url;\n}\n\n/**\n * Normalize a single result from the Muse API response. Exported for unit tests.\n *\n * Field mapping:\n *   name              → title\n *   refs.landing_page → url\n *   company.name      → company\n *   locations[0].name → location\n *\n * Returns null when required fields (title or url) are missing or invalid.","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/providers/themuse.mjs#L2-L38","documentation":"assertMuseUrl wraps new URL in try/catch and throws 'themuse: invalid URL' on a parse failure. In the shipped provider this guard is only ever called with the hardcoded constant FEED_BASE ('https://www.themuse.com/api/public/jobs'), so the error is effectively unreachable unless FEED_BASE is changed or the function is called with external input.","triggerScenarios":"FEED_BASE was edited to a malformed value, or assertMuseUrl is invoked from a test/fork with a non-URL string. The provider takes no URL from config (fetch ignores _entry), so config cannot trigger it.","commonSituations":"A fork changes FEED_BASE without quoting/validating; a unit test passes bad input to the exported guard.","solutions":["Restore FEED_BASE to 'https://www.themuse.com/api/public/jobs'","If you intentionally retarget the feed, supply a valid absolute URL","Do not call assertMuseUrl with user/config URLs — it validates the internal feed constant only"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// assertMuseUrl validates a constant; lint that FEED_BASE is a valid URL at startup.\ntry { new URL(FEED_BASE); } catch { throw new Error('themuse: FEED_BASE is not a valid URL'); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not edit FEED_BASE without re-validating it parses.","Do not call assertMuseUrl with external URLs."],"tags":["ssrf-guard","url-validation","themuse","unreachable-defensive"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}