santifer/career-ops · error · Error

pinpoint: untrusted hostname "${parsed.hostname}" — must mat

Error message

pinpoint: untrusted hostname "${parsed.hostname}" — must match <slug>.pinpointhq.com

What it means

The pinpoint provider rejects an API URL whose hostname does not match the strict allowlist regex PINPOINT_HOST_RE (/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.pinpointhq\.com$/). This is an SSRF guard: it pins every request to a genuine <slug>.pinpointhq.com tenant subdomain so a crafted entry cannot redirect the fetch to an attacker-controlled or internal host. The slug must start and end alphanumeric with optional interior hyphens.

Source

Thrown at providers/pinpoint.mjs:34

// The tenant label must be a valid DNS label: it may contain hyphens but must
// not start or end with one (so `acme-.pinpointhq.com` is rejected). The
// optional trailing group keeps single-character labels (e.g. `a.pinpointhq.com`)
// valid. detect() and fetch() both route through this constant via
// resolveApiUrl()/assertPinpointUrl(), so the stricter check applies everywhere.
const PINPOINT_HOST_RE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.pinpointhq\.com$/;

/** @param {string} url */
function assertPinpointUrl(url) {
  let parsed;
  try {
    parsed = new URL(url);
  } catch {
    throw new Error(`pinpoint: invalid URL: ${url}`);
  }
  if (parsed.protocol !== 'https:') throw new Error(`pinpoint: URL must use HTTPS: ${url}`);
  if (!PINPOINT_HOST_RE.test(parsed.hostname)) {
    throw new Error(`pinpoint: untrusted hostname "${parsed.hostname}" — must match <slug>.pinpointhq.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 (!PINPOINT_HOST_RE.test(parsed.hostname)) return null;
  return `https://${parsed.hostname}/postings.json`;
}

View on GitHub (pinned to 9b17a8ac97)

Solutions

  1. Confirm the entry's careers_url is literally https://<slug>.pinpointhq.com where <slug> is lowercase, starts and ends with a letter or digit, and uses only hyphens in between.
  2. If the tenant uses a branded custom domain, the pinpoint provider cannot auto-derive it — set provider explicitly to the correct provider or supply api: with the canonical pinpointhq.com subdomain.
  3. Strip any trailing slash, port, or uppercase characters from the hostname before validation.
  4. Verify the entry object passed to fetch() has not been mutated downstream to carry a resolved URL from a different host.

Example fix

// before
const entry = { name: 'Acme', careers_url: 'https://jobs.acme.com' };
// after — canonical Pinpoint subdomain
const entry = { name: 'Acme', careers_url: 'https://acme.pinpointhq.com' };
Defensive patterns

Strategy: validation

Validate before calling

const PINPOINT_HOST_RE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.pinpointhq\.com$/;
function isValidPinpointUrl(url) {
  try {
    const p = new URL(url);
    return p.protocol === 'https:' && PINPOINT_HOST_RE.test(p.hostname);
  } catch { return false; }
}
// call before provider.fetch
if (!isValidPinpointUrl(entry.careers_url)) {
  console.warn(`skip ${entry.name}: not a valid pinpointhq.com URL`);
}

Type guard

null

Try / catch

try {
  await provider.fetch(entry, ctx);
} catch (e) {
  if (/pinpoint: untrusted hostname/.test(e.message)) {
    // config issue, not transient — log and skip this entry
    console.warn(`[skip] ${entry.name}: ${e.message}`);
  } else throw e;
}

Prevention

When it happens

Trigger: assertPinpointUrl throws when parsed.hostname fails the regex — e.g. a careers_url pointing to a custom branded domain (jobs.acme.com), a hostname with uppercase letters (Acme.pinpointhq.com), a leading/trailing hyphen in the slug (-acme.pinpointhq.com), or a hostname like pinpointhq.com with no slug prefix at all.

Common situations: A job_boards entry was auto-detected from a non-Pinpoint URL but routed to the pinpoint provider; a user pasted a Pinpoint vanity/branded domain that does not carry the pinpointhq.com suffix; the entry's careers_url was typo'd with a trailing dot or wrong TLD.

Related errors


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