santifer/career-ops · error · Error

workable: untrusted hostname "${parsed.hostname}" — must be

Error message

workable: untrusted hostname "${parsed.hostname}" — must be one of: ${[...ALLOWED_WORKABLE_HOSTS].join(', ')}

What it means

SSRF guard: the URL parsed and is https, but its hostname is not in ALLOWED_WORKABLE_HOSTS (apply.workable.com only). Built URLs always target apply.workable.com, so this fires only if a template host is changed OR the allowlist is emptied/mis-edited.

Source

Thrown at providers/workable.mjs:118

// same host, so this process never needs more than one in-flight request to
// it at a time.
let workableQueue = Promise.resolve();
function serialized(fn) {
  const result = workableQueue.then(fn, fn);
  workableQueue = result.then(() => undefined, () => undefined);
  return result;
}

function assertWorkableUrl(url) {
  let parsed;
  try {
    parsed = new URL(url);
  } catch {
    throw new Error(`workable: invalid URL: ${url}`);
  }
  if (parsed.protocol !== 'https:') throw new Error(`workable: URL must use HTTPS: ${url}`);
  if (!ALLOWED_WORKABLE_HOSTS.has(parsed.hostname)) {
    throw new Error(`workable: untrusted hostname "${parsed.hostname}" — must be one of: ${[...ALLOWED_WORKABLE_HOSTS].join(', ')}`);
  }
  return url;
}

/**
 * Extract the account slug from a tracked_companies entry's careers_url.
 * @returns {string|null}
 */
export function resolveWorkableSlug(entry) {
  const raw = entry && 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;

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Keep the templates on apply.workable.com and keep that host in ALLOWED_WORKABLE_HOSTS.

Example fix

// before
const ALLOWED_WORKABLE_HOSTS = new Set([]);
// after
const ALLOWED_WORKABLE_HOSTS = new Set(['apply.workable.com']);
Defensive patterns

Strategy: validation

Validate before calling

for (const tpl of [widgetUrlFor, feedUrlFor]) {
  const u = new URL(tpl("acme"));
  if (!ALLOWED_WORKABLE_HOSTS.has(u.hostname))
    throw new Error("workable: template host not in allowlist");
}

Type guard

const isAllowedHost = (s, set) => { try { return set.has(new URL(s).hostname); } catch { return false; } };

Prevention

When it happens

Trigger: A maintainer edits a URL template to a different host, or removes apply.workable.com from ALLOWED_WORKABLE_HOSTS.

Common situations: Refactor that accidentally clears the allowlist; a bad merge.

Related errors


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