santifer/career-ops · warning · Error
eightfold: untrusted hostname "${parsed.hostname}" — must ma
Error message
eightfold: untrusted hostname "${parsed.hostname}" — must match *.eightfold.ai What it means
Thrown by eightfold's assertEightfoldUrl when the URL is valid https but its hostname does not match /^[a-z0-9-]+\.eightfold\.ai$/i (EIGHTFOLD_HOST_RE). Defense-in-depth: fetch() only ever passes buildApiUrl output, whose host is the resolveTenant-validated tenant.host, so the guard is unreachable through normal use. Reachable only via a direct assertEightfoldUrl call.
Source
Thrown at providers/eightfold.mjs:73
const RETRY_POLICY = { retries: 3, baseDelayMs: 500, maxDelayMs: 8_000 };
/**
* SSRF guard — every request URL passes through here before it is fetched.
*
* @param {string} url
* @returns {string} the same URL, when it is a trusted Eightfold endpoint.
*/
function assertEightfoldUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`eightfold: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`eightfold: URL must use HTTPS: ${url}`);
if (!EIGHTFOLD_HOST_RE.test(parsed.hostname)) {
throw new Error(`eightfold: untrusted hostname "${parsed.hostname}" — must match *.eightfold.ai`);
}
return url;
}
/** @param {number} ms @param {any} ctx */
function sleep(ms, ctx) {
if (typeof ctx?.sleep === 'function') return ctx.sleep(ms);
return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
* Eightfold reports timestamps as epoch SECONDS (`t_create`, `t_update`), not
* the ISO strings every other provider gets. Converted here; anything
* non-finite or non-positive is dropped rather than guessed at.
*
* @param {unknown} value
* @returns {number|undefined} epoch ms, or undefined.
*/View on GitHub (pinned to 9b17a8ac97)
Solutions
- For direct callers, pass only https://<tenant>.eightfold.ai/... URLs.
- For fetch() use, point api:/careers_url at the canonical <tenant>.eightfold.ai host (a branded CNAME is deliberately rejected — see error 177).
- Treat a production hit as a signal that resolveTenant and assertEightfoldUrl have diverged.
Example fix
// before — branded CNAME host
assertEightfoldUrl('https://careers.bayer.com/api/apply/v2/jobs?start=0&num=10');
// after — canonical eightfold.ai tenant host
assertEightfoldUrl('https://bayer.eightfold.ai/api/apply/v2/jobs?start=0&num=10'); Defensive patterns
Strategy: validation
Validate before calling
const EIGHTFOLD_HOST_RE = /^[a-z0-9-]+\.eightfold\.ai$/i;
function isEightfoldHost(u) { try { return EIGHTFOLD_HOST_RE.test(new URL(u).hostname); } catch { return false; } } Type guard
function isEightfoldEndpoint(u) {
if (typeof u !== 'string' || !u) return false;
try {
const p = new URL(u);
return p.protocol === 'https:' && /^[a-z0-9-]+\.eightfold\.ai$/i.test(p.hostname);
} catch { return false; }
} Try / catch
try { assertEightfoldUrl(url); }
catch (e) {
if (/^eightfold: untrusted hostname/.test(e.message)) { /* branded CNAME or wrong host — skip */ }
else throw e;
} Prevention
- No action for normal scans — tenant host is pre-validated by resolveTenant.
- For fetch() use, point api:/careers_url at <tenant>.eightfold.ai, not a branded CNAME (see error 177).
- The API is intentionally host-pinned to *.eightfold.ai.
When it happens
Trigger: assertEightfoldUrl is called directly with an https URL on a non-*.eightfold.ai host. fetch() validates the tenant host via resolveTenant (which applies EIGHTFOLD_HOST_RE) before any URL is built, so no entry config reaches this branch.
Common situations: A direct integration or test pointing at a branded CNAME (e.g. careers.company.com) or a mock host. Production scans fail earlier at resolveTenant (error 177), not here.
Related errors
- comeet: untrusted hostname "${parsed.hostname}" — must be ${
- echojobs: untrusted hostname "${parsed.hostname}" — must be
- eightfold: invalid URL: ${url}
- eightfold: URL must use HTTPS: ${url}
- comeet: invalid URL: ${redactToken(url)}
AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13).
Data as JSON: /api/errors/c4e525f55b05f12c.
Report an issue: GitHub.