{"record":{"id":"7f8a80765fc731ed","repo":"santifer/career-ops","slug":"a16z-speedrun-talent-untrusted-hostname-parsed","errorCode":null,"errorMessage":"a16z-speedrun-talent: untrusted hostname \"${parsed.hostname}\" — must be ${TRUSTED_HOST}","messagePattern":"a16z-speedrun-talent: untrusted hostname \"(.+?)\" — must be (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/a16z-speedrun-talent.mjs","lineNumber":48,"sourceCode":"// Runaway bound, not a coverage target: iteration already stops at the\n// feed's reported total_pages (or a short page), so on an honest feed the\n// cap costs nothing and full-board sweeps keep working as the board grows.\n// It only bites a misbehaving feed or an absurd max_pages entry — so it\n// sits well above plausible board size (~353 pages / ~17.6k jobs as of\n// 2026-08), same policy as workday.mjs's cap.\nconst MAX_PAGES_CAP = 1000;\n\n/** @param {string} url */\nfunction assertFeedUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`a16z-speedrun-talent: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`a16z-speedrun-talent: URL must use HTTPS: ${url}`);\n  if (parsed.hostname !== TRUSTED_HOST) {\n    throw new Error(`a16z-speedrun-talent: 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/** Optional server-side query: `q:` on the entry, else joined `keywords:`. */\nfunction resolveQuery(entry) {\n  if (typeof entry?.q === 'string' && entry.q.trim()) return entry.q.trim();\n  if (Array.isArray(entry?.keywords) && entry.keywords.length > 0) {\n    const joined = entry.keywords.filter((k) => typeof k === 'string' && k.trim()).join(' ').trim();\n    if (joined) return joined;\n  }","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/providers/a16z-speedrun-talent.mjs#L30-L66","documentation":"The final feed-URL guard pins the hostname to TRUSTED_HOST (the a16z speedrun talent API host). Any other hostname is rejected as an SSRF allowlist violation — the provider only ever fetches from its one known feed host.","triggerScenarios":"The parsed URL hostname differs from TRUSTED_HOST: a wrong subdomain (e.g. 'www.' variant), a different domain, or an internal host/IP a redirect or tampered constant tried to reach. Server-side redirects are already blocked by redirect:'error', so this catches a directly-misconfigured host.","commonSituations":"FEED_BASE edited to the marketing-site host instead of the API host; TRUSTED_HOST not updated after upstream renamed their API host; subdomain mismatch.","solutions":["Confirm TRUSTED_HOST at the top of providers/a16z-speedrun-talent.mjs matches the real API host and set FEED_BASE to that exact host.","Do not use subdomain variants unless TRUSTED_HOST is updated to allow them (by design it stays a single tight host)."],"exampleFix":"// before\nconst TRUSTED_HOST = 'a16z.com'; // wrong — that is the marketing site\nconst FEED_BASE = `https://${TRUSTED_HOST}/api/talent`;\n\n// after — the real API host\nconst TRUSTED_HOST = 'speedrun.a16z.com';\nconst FEED_BASE = `https://${TRUSTED_HOST}/api/talent`;","handlingStrategy":"validation","validationCode":"const TRUSTED_HOST = 'speedrun.a16z.com';\nfunction isTrustedFeedUrl(u) {\n  try {\n    const p = new URL(u);\n    return p.protocol === 'https:' && p.hostname === TRUSTED_HOST;\n  } catch { return false; }\n}\nif (!isTrustedFeedUrl(FEED_BASE)) throw new Error('a16z feed host not trusted');","typeGuard":"/** @param {unknown} u @param {string} host @returns {u is string} */\nfunction isTrustedHostUrl(u, host) {\n  if (typeof u !== 'string') return false;\n  try { return new URL(u).hostname === host; } catch { return false; }\n}","tryCatchPattern":"try { assertFeedUrl(url); } catch (err) {\n  if (/untrusted hostname/.test(err.message)) console.error('a16z feed host must be', TRUSTED_HOST);\n  throw err;\n}","preventionTips":["Keep TRUSTED_HOST allowlisted and lint against silent widening.","Pair with redirect:'error' on fetch (this provider does) to close the redirect-SSRF vector."],"tags":["a16z","ssrf-guard","allowlist","provider","security","url"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}