santifer/career-ops · error · Error

recruitee: URL must use HTTPS: ${url}

Error message

recruitee: URL must use HTTPS: ${url}

What it means

assertRecruiteeUrl rejects any URL whose protocol is not exactly 'https:'. The check runs after the URL parses successfully but before the hostname regex. Plain HTTP is blocked to prevent cleartext interception of board data and to enforce transport security on the Recruitee API.

Source

Thrown at providers/recruitee.mjs:19

// @ts-check
/** @typedef {import('./_types.js').Provider} Provider */

// Recruitee provider — hits the public per-tenant offers API.
// Auto-detects from careers_url pattern `https://<slug>.recruitee.com`.
// Per-tenant subdomains are the variable part — SSRF defence uses a
// regex match on `<safe-slug>.recruitee.com` rather than a static
// allowlist.

const RECRUITEE_HOST_RE = /^[a-z0-9][a-z0-9-]*\.recruitee\.com$/;

function assertRecruiteeUrl(url) {
  let parsed;
  try {
    parsed = new URL(url);
  } catch {
    throw new Error(`recruitee: invalid URL: ${url}`);
  }
  if (parsed.protocol !== 'https:') throw new Error(`recruitee: URL must use HTTPS: ${url}`);
  if (!RECRUITEE_HOST_RE.test(parsed.hostname)) {
    throw new Error(`recruitee: untrusted hostname "${parsed.hostname}" — must match <slug>.recruitee.com`);
  }
  return url;
}

function resolveApiUrl(entry) {
  const raw = typeof entry.careers_url === 'string' ? entry.careers_url : '';
  if (!raw) return null;
  let parsed;
  try {
    parsed = new URL(raw);
  } catch {
    return null;
  }
  if (parsed.protocol !== 'https:') return null;
  if (!RECRUITEE_HOST_RE.test(parsed.hostname)) return null;
  return `https://${parsed.hostname}/api/offers/`;

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Change the scheme to https:// in the source config.
  2. Upgrade the URL before validation: url.replace(/^http:\/\//, 'https://').
  3. Audit all entries for http:// prefixes and normalize them to https://.

Example fix

// before
{ careers_url: 'http://acme.recruitee.com' }
// after
{ careers_url: 'https://acme.recruitee.com' }
Defensive patterns

Strategy: validation

Validate before calling

function ensureHttps(raw) {
  if (typeof raw !== 'string') return null;
  return raw.replace(/^http:\/\//i, 'https://');
}
entry.careers_url = ensureHttps(entry.careers_url);

Type guard

null

Try / catch

try {
  await provider.fetch(entry, ctx);
} catch (e) {
  if (/must use HTTPS/.test(e.message)) {
    console.warn(`[fix] upgrading ${entry.name} to https and retrying`);
    entry.careers_url = entry.careers_url.replace(/^http:/i, 'https:');
  } else throw e;
}

Prevention

When it happens

Trigger: A careers_url using http://<slug>.recruitee.com; a URL whose scheme is http: even though the host is otherwise valid.

Common situations: A legacy config or database column still stores http:// URLs; the URL was constructed by string concatenation with 'http://'; a redirect or scrape captured the http variant.

Related errors


AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13). Data as JSON: /api/errors/ba0bb1cf4350a99d. Report an issue: GitHub.