santifer/career-ops · error · Error
himalayas: untrusted hostname "${parsed.hostname}" - must be
Error message
himalayas: untrusted hostname "${parsed.hostname}" - must be ${TRUSTED_HOST} What it means
Thrown by assertHimalayasUrl when the URL's hostname is not exactly himalayas.app (subdomains are NOT allowed here — the check is strict equality, unlike the cleanHimalayasUrl helper which tolerates *.himalayas.app). This is the core SSRF allowlist guard. Shipped fetch() passes only the hardcoded himalayas.app constant, so it cannot fire unless the constant or the function's input changes.
Source
Thrown at providers/himalayas.mjs:24
// full feed is fetched so scan.mjs's title_filter / location_filter can do
// the local gating consistently with other zero-token board providers.
//
// Wire in via a `job_boards:` entry with `provider: himalayas`.
const FEED_URL = 'https://himalayas.app/jobs/api?limit=50';
const TRUSTED_HOST = 'himalayas.app';
/** @param {string} url */
function assertHimalayasUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`himalayas: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`himalayas: URL must use HTTPS: ${url}`);
if (parsed.hostname !== TRUSTED_HOST) {
throw new Error(`himalayas: untrusted hostname "${parsed.hostname}" - must be ${TRUSTED_HOST}`);
}
return url;
}
function cleanText(value) {
return typeof value === 'string' ? value.trim() : '';
}
function cleanHimalayasUrl(value) {
const raw = cleanText(value);
if (!raw) return '';
try {
const parsed = new URL(raw);
const host = parsed.hostname.toLowerCase();
const trusted = host === TRUSTED_HOST || host.endsWith(`.${TRUSTED_HOST}`);
return parsed.protocol === 'https:' && trusted ? parsed.href : '';
} catch {
return '';View on GitHub (pinned to 9b17a8ac97)
Solutions
- Keep FEED_URL on the bare himalayas.app host, or if a subdomain is genuinely required, update the assert to allow *.himalayas.app (mirror cleanHimalayasUrl's logic).
- Never route untrusted entry input through assertHimalayasUrl without first confirming the host is allowlisted.
- Document any host allowlist change next to TRUSTED_HOST so the SSRF posture stays explicit.
Example fix
// before (strict — rejects subdomains)
if (parsed.hostname !== TRUSTED_HOST) { throw ... }
// after (allow subdomains, mirroring cleanHimalayasUrl)
if (parsed.hostname !== TRUSTED_HOST && !parsed.hostname.endsWith('.' + TRUSTED_HOST)) { throw ... } Defensive patterns
Strategy: validation
Validate before calling
// For caller input, confirm the host is allowlisted before the assert throws.
const TRUSTED_HOST = 'himalayas.app';
function isTrustedHimalayasHost(url) {
const u = new URL(url);
return u.hostname === TRUSTED_HOST; // assert is strict — subdomains NOT allowed
} Type guard
/** True for a URL on exactly himalayas.app (no subdomains, per the assert). */
function isHimalayasTrusted(url) {
try {
const u = new URL(url);
return u.protocol === 'https:' && u.hostname === 'himalayas.app';
} catch { return false; }
} Try / catch
try {
return await himalayasProvider.fetch(entry, ctx);
} catch (err) {
if (/untrusted hostname/.test(err.message)) {
console.error(`himalayas: host not allowlisted — ${err.message}`);
}
throw err;
} Prevention
- Keep FEED_URL on the bare himalayas.app host; if a subdomain is genuinely needed, widen the assert to *.himalayas.app deliberately and document it.
- Treat the SSRF allowlist as load-bearing — never widen it casually or route untrusted input through it.
- Note cleanHimalayasUrl (the per-job helper) DOES allow subdomains; the request assert does not. Do not assume parity.
When it happens
Trigger: Editing FEED_URL to a different host (e.g. a CDN or mirror domain); reusing assertHimalayasUrl on entry.api that points at a subdomain like api.himalayas.app (the strict equality rejects subdomains even though cleanHimalayasUrl would accept them); a DNS-rebinding-style attempt to route the request off-host.
Common situations: Switching to a subdomain endpoint and assuming the assert allows it; a fork adding a configurable host without widening the allowlist; a malicious/typo entry URL routed through the assert.
Related errors
- himalayas: invalid URL: ${url}
- himalayas: URL must use HTTPS: ${url}
- jobspresso: untrusted hostname "${parsed.hostname}" - must b
- comeet: invalid URL: ${redactToken(url)}
- comeet: URL must use HTTPS: ${redactToken(url)}
AI-assisted analysis of santifer/career-ops@9b17a8ac97 (2026-08-13).
Data as JSON: /api/errors/bcd95b182d24389c.
Report an issue: GitHub.