{"record":{"id":"48c4f9882db75800","repo":"santifer/career-ops","slug":"pythonorg-url-must-use-https-url","errorCode":null,"errorMessage":"pythonorg: URL must use HTTPS: ${url}","messagePattern":"pythonorg: URL must use HTTPS: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/pythonorg.mjs","lineNumber":28,"sourceCode":"// The feed is public, no-auth, and RSS 2.0 XML.\n//\n// Each <item> exposes <title> (typically \"{Role}, {Company}\"), <link>,\n// and <description> (the first line typically contains the location).\n//\n// Wire in via a `job_boards:` entry with `provider: pythonorg`.\n\nconst FEED_URL = 'https://www.python.org/jobs/feed/rss/';\nconst TRUSTED_HOST = 'python.org';\n\n/** @param {string} url */\nexport function assertPythonOrgUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`pythonorg: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`pythonorg: URL must use HTTPS: ${url}`);\n  const host = parsed.hostname.toLowerCase();\n  const trusted = host === TRUSTED_HOST || host.endsWith(`.${TRUSTED_HOST}`);\n  if (!trusted) {\n    throw new Error(`pythonorg: untrusted hostname \"${parsed.hostname}\" — must be ${TRUSTED_HOST}`);\n  }\n  return url;\n}\n\n// NaN-safe Date.parse — `|| undefined` would also coerce a valid epoch 0.\nfunction toEpochMs(value) {\n  if (!value) return undefined;\n  const parsed = Date.parse(value);\n  return Number.isNaN(parsed) ? undefined : parsed;\n}\n\nfunction fallbackCompany(entry) {\n  return typeof entry?.name === 'string' && entry.name.trim() ? entry.name.trim() : 'Python.org';\n}","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/santifer/career-ops/blob/e7abd431fce9348a95261acac9e0c14779c35df8/providers/pythonorg.mjs#L10-L46","documentation":"assertPythonOrgUrl rejects any URL whose protocol is not https:. The python.org feed provider only talks to the HTTPS endpoint (the feed is public at https://www.python.org/jobs/feed/rss/), so an http: or other-scheme URL is refused even if it is otherwise well-formed. This blocks accidental plaintext fetching and SSRF-style scheme abuse (file:, javascript:, etc.).","triggerScenarios":"Calling assertPythonOrgUrl with a URL whose parsed.protocol !== 'https:' — typically 'http://www.python.org/jobs/feed/rss/', but also file: or custom-scheme URLs that pass URL parsing.","commonSituations":"Config entry written with http:// out of habit; a redirect/downgrade helper rewriting https to http; tests using a local http:// mock server URL directly instead of stubbing the fetch; copying an insecure mirror link.","solutions":["Change the URL scheme to https: (e.g. 'https://www.python.org/jobs/feed/rss/') in the config or call site","For local testing, stub ctx/fetch layer rather than pointing the provider at an http:// URL","If you control the caller, validate the scheme before invoking: new URL(url).protocol === 'https:'","Confirm no middleware rewrites or normalizes the configured URL to http"],"exampleFix":"// before\nassertPythonOrgUrl('http://www.python.org/jobs/feed/rss/');\n// after\nassertPythonOrgUrl('https://www.python.org/jobs/feed/rss/');","handlingStrategy":"validation","validationCode":"function isHttpsUrl(url) {\n  try { return new URL(url).protocol === 'https:'; } catch { return false; }\n}\n// if (!isHttpsUrl(cfg.feedUrl)) throw new Error('pythonorg feedUrl must be https');","typeGuard":"function isHttpsPythonOrgUrl(value) {\n  if (typeof value !== 'string') return false;\n  try { const u = new URL(value); return u.protocol === 'https:' && u.hostname.endsWith('python.org'); } catch { return false; }\n}","tryCatchPattern":"try {\n  assertPythonOrgUrl(cfg.feedUrl);\n} catch (e) {\n  if (e.message.startsWith('pythonorg: URL must use HTTPS')) {\n    console.error(`Config error: ${cfg.feedUrl} must use https:// — fix the scheme`);\n  } else throw e;\n}","preventionTips":["Default to https:// in every config URL; never write http:// even for 'known safe' hosts","Add a startup validation pass that rejects non-https board URLs before any network work","Don't point providers at local http:// mock servers — stub the fetch layer in tests instead","Check for middleware/normalizers that might downgrade or rewrite the scheme"],"tags":["url-validation","https","security","pythonorg"],"backgroundTag":"invalid-url","analyzedSha":"e7abd431fce9348a95261acac9e0c14779c35df8","analyzedAt":"2026-09-22T13:19:01.448Z","contentChangedAt":"2026-09-22T13:19:01.448Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}