santifer/career-ops · error · Error
yourator: untrusted hostname "${parsed.hostname}" — must be
Error message
yourator: untrusted hostname "${parsed.hostname}" — must be ${TRUSTED_HOST} What it means
After confirming HTTPS, assertYouratorUrl pins the hostname to TRUSTED_HOST (www.yourator.co, per the provider's documented API at https://www.yourator.co/api/v4/jobs). Any other hostname is rejected to prevent SSRF-style abuse where a crafted config points the fetcher at an internal or attacker-controlled host. The error names the offending hostname and the required one.
Source
Thrown at providers/yourator.mjs:85
const FEED_BASE = `${SITE_ORIGIN}/api/v4/jobs`;
const TRUSTED_HOST = 'www.yourator.co';
// Safety bound only — the loop stops on payload.hasMore. The live board was 88
// pages on 2026-08-18; this leaves room to grow without silently truncating.
const DEFAULT_MAX_PAGES = 120;
const MAX_PAGES_CAP = 500;
const PAGE_DELAY_MS = 200;
/** @param {string} url */
function assertYouratorUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`yourator: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`yourator: URL must use HTTPS: ${url}`);
if (parsed.hostname !== TRUSTED_HOST) {
throw new Error(`yourator: untrusted hostname "${parsed.hostname}" — must be ${TRUSTED_HOST}`);
}
return url;
}
/** Resolve the page cap: a positive integer `max_pages` on the entry, capped. */
function resolveMaxPages(entry) {
const v = entry?.max_pages;
if (Number.isInteger(v) && v > 0) return Math.min(v, MAX_PAGES_CAP);
return DEFAULT_MAX_PAGES;
}
/**
* Canonical URL for a posting — Source Indexing Policy rule 2, "the shortest
* verifiable path to the employer the source exposes".
*
* Prefers `thirdPartyUrl` (the employer's own ATS page), with the board's
* `utm_*` ad parameters stripped. Accepts any https: origin — the value is
* display-only and never fetched here. Falls back to the Yourator posting pageView on GitHub (pinned to 1696bec4d0)
Solutions
- Set the hostname to exactly the trusted host: https://www.yourator.co/... (with www.).
- Compare `new URL(url).hostname` against 'www.yourator.co' before invoking the provider.
- Remove any host-rewriting proxy/mirror from the configuration; the provider only fetches the official domain.
Example fix
// before careers_url: https://yourator.co/jobs // after careers_url: https://www.yourator.co/jobs
Defensive patterns
Strategy: validation
Validate before calling
const TRUSTED_HOST = 'www.yourator.co';
export function isTrustedYouratorUrl(u) {
try { return new URL(u).hostname === TRUSTED_HOST; } catch { return false; }
}
if (!isTrustedYouratorUrl(entry.careers_url)) entry.careers_url = 'https://www.yourator.co/jobs'; Type guard
function isYouratorUrl(u) {
try {
const p = new URL(u);
return p.protocol === 'https:' && p.hostname === 'www.yourator.co';
} catch { return false; }
} Try / catch
try {
scanYourator(entry);
} catch (e) {
if (e.message.includes('untrusted hostname')) {
console.error(`Bad host in ${entry.careers_url}; defaulting to https://www.yourator.co/jobs`);
scanYourator({ ...entry, careers_url: 'https://www.yourator.co/jobs' });
} else throw e;
} Prevention
- Use the exact documented URL https://www.yourator.co/jobs — never omit the www. or swap to a subdomain.
- Never point provider fetch URLs at proxies or mirrors; host pinning is intentional (SSRF guard).
- Unit-test provider config against a hostname allowlist before executing scans.
When it happens
Trigger: assertYouratorUrl receives an https: URL whose parsed.hostname !== TRUSTED_HOST — e.g. https://yourator.co/jobs (missing www.), https://api.yourator.co/v4/jobs, https://evil.example.com/jobs, or a copy of the feed URL served from a mirror domain.
Common situations: Omitting the www. prefix because the site resolves either way in a browser; pointing at an API subdomain copied from a blog post; a malicious or typosquatted mirror in config; environment-specific overrides that rewrite the host.
Related errors
- ashby: untrusted hostname "${parsed.hostname}" — must be one
- flowxtra: untrusted hostname "${parsed.hostname}" — must be
- refusing to archive restricted destination: ${preGuard.reaso
- refusing to archive restricted destination after redirect: $
- Invalid or blocked URL: ${rejected.reason}
AI-assisted analysis of santifer/career-ops@1696bec4d0 (2026-09-01).
Data as JSON: /api/errors/3322aabccc6ba045.
Report an issue: GitHub.