santifer/career-ops · error · Error

pythonorg: URL must use HTTPS

Error message

pythonorg: URL must use HTTPS: ${url}

What it means

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.).

Solutions

  1. Change the URL scheme to https: (e.g. 'https://www.python.org/jobs/feed/rss/') in the config or call site
  2. For local testing, stub ctx/fetch layer rather than pointing the provider at an http:// URL
  3. If you control the caller, validate the scheme before invoking: new URL(url).protocol === 'https:'
  4. Confirm no middleware rewrites or normalizes the configured URL to http

Example fix

// before
assertPythonOrgUrl('http://www.python.org/jobs/feed/rss/');
// after
assertPythonOrgUrl('https://www.python.org/jobs/feed/rss/');
Defensive patterns

Strategy: validation

Validate before calling

function isHttpsUrl(url) {
  try { return new URL(url).protocol === 'https:'; } catch { return false; }
}
// if (!isHttpsUrl(cfg.feedUrl)) throw new Error('pythonorg feedUrl must be https');

Type guard

function isHttpsPythonOrgUrl(value) {
  if (typeof value !== 'string') return false;
  try { const u = new URL(value); return u.protocol === 'https:' && u.hostname.endsWith('python.org'); } catch { return false; }
}

Try / catch

try {
  assertPythonOrgUrl(cfg.feedUrl);
} catch (e) {
  if (e.message.startsWith('pythonorg: URL must use HTTPS')) {
    console.error(`Config error: ${cfg.feedUrl} must use https:// — fix the scheme`);
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of santifer/career-ops@e7abd431fc (2026-09-22). Data as JSON: /api/errors/48c4f9882db75800. Report an issue: GitHub.

Appendix: source

Thrown at providers/pythonorg.mjs:28

// The feed is public, no-auth, and RSS 2.0 XML.
//
// Each <item> exposes <title> (typically "{Role}, {Company}"), <link>,
// and <description> (the first line typically contains the location).
//
// Wire in via a `job_boards:` entry with `provider: pythonorg`.

const FEED_URL = 'https://www.python.org/jobs/feed/rss/';
const TRUSTED_HOST = 'python.org';

/** @param {string} url */
export function assertPythonOrgUrl(url) {
  let parsed;
  try {
    parsed = new URL(url);
  } catch {
    throw new Error(`pythonorg: invalid URL: ${url}`);
  }
  if (parsed.protocol !== 'https:') throw new Error(`pythonorg: URL must use HTTPS: ${url}`);
  const host = parsed.hostname.toLowerCase();
  const trusted = host === TRUSTED_HOST || host.endsWith(`.${TRUSTED_HOST}`);
  if (!trusted) {
    throw new Error(`pythonorg: untrusted hostname "${parsed.hostname}" — must be ${TRUSTED_HOST}`);
  }
  return url;
}

// NaN-safe Date.parse — `|| undefined` would also coerce a valid epoch 0.
function toEpochMs(value) {
  if (!value) return undefined;
  const parsed = Date.parse(value);
  return Number.isNaN(parsed) ? undefined : parsed;
}

function fallbackCompany(entry) {
  return typeof entry?.name === 'string' && entry.name.trim() ? entry.name.trim() : 'Python.org';
}

View on GitHub (pinned to e7abd431fc)