santifer/career-ops · error · Error
torre: untrusted hostname "${parsed.hostname}" — must be ${T
Error message
torre: untrusted hostname "${parsed.hostname}" — must be ${TRUSTED_API_HOST} What it means
After passing scheme checks, assertTorreUrl enforces a single trusted API host (TRUSTED_API_HOST). This error is thrown when the hostname differs — including lookalike/subdomain variants. Like its Muse counterpart, this is the SSRF/pin allowlist that stops fetches to attacker-controlled or redirected hosts.
Source
Thrown at providers/torre.mjs:94
'potential-to-develop',
'1-plus-year',
'2-plus-years',
'3-plus-years',
'5-plus-years',
]);
const DEFAULT_EXPERIENCE = '1-plus-year';
/** @param {string} url */
function assertTorreUrl(url) {
let parsed;
try {
parsed = new URL(url);
} catch {
throw new Error(`torre: invalid URL: ${url}`);
}
if (parsed.protocol !== 'https:') throw new Error(`torre: URL must use HTTPS: ${url}`);
if (parsed.hostname !== TRUSTED_API_HOST) {
throw new Error(`torre: untrusted hostname "${parsed.hostname}" — must be ${TRUSTED_API_HOST}`);
}
return url;
}
/**
* Build the search body from the portal entry. Only filters proven to affect
* `total` are emitted — see the header note. Exported for tests.
*
* @param {any} entry
* @returns {object}
*/
export function buildTorreQuery(entry) {
/** @type {Record<string, unknown>} */
const body = {};
const search = typeof entry?.search === 'string' ? entry.search.trim() : '';
if (search) {
// `experience` is mandatory here — omitting it is a hard 500, so it isView on GitHub (pinned to 1696bec4d0)
Solutions
- Correct the hostname to exactly the pinned TRUSTED_API_HOST (check the constant at the top of providers/torre.mjs).
- Strip redirect/tracking wrappers to recover the genuine Torre API URL before validating.
- If Torre changed its API host officially, verify and update TRUSTED_API_HOST in providers/torre.mjs — do not loosen the check to a suffix match.
- Route URLs for other hosts to their proper providers instead of forcing them through the Torre provider.
Example fix
// before (provider pinned to api.torre.ai)
assertTorreUrl('https://torre.co/api/v2');
// Error: untrusted hostname "torre.co" — must be api.torre.ai
// after
assertTorreUrl('https://api.torre.ai/api/v2'); Defensive patterns
Strategy: validation
Validate before calling
const TRUSTED_API_HOST = 'api.torre.ai'; // match the constant in providers/torre.mjs
function isTrustedTorreUrl(url) {
try {
const u = new URL(url);
return u.protocol === 'https:' && u.hostname === TRUSTED_API_HOST;
} catch { return false; }
} Type guard
function isTorreApiUrl(v) {
if (typeof v !== 'string') return false;
try {
const u = new URL(v);
return u.protocol === 'https:' && u.hostname === 'api.torre.ai';
} catch { return false; }
} Try / catch
try {
assertTorreUrl(url);
} catch (err) {
if (String(err.message).includes('untrusted hostname')) {
console.error(`Rejecting non-Torre host (possible SSRF/mirror): ${err.message}`);
return null; // skip this URL
} else throw err;
} Prevention
- Pin the exact host (subdomain included) in config; check the constant in providers/torre.mjs if Torre migrates domains.
- Treat URLs from aggregators/emails as untrusted — resolve redirects and re-validate.
- Never weaken the host check to includes()/suffix matching.
- Route each job board's URLs to its own provider rather than forcing one validator.
When it happens
Trigger: Calling assertTorreUrl with a URL on a different host or subdomain than the pinned Torre API host — e.g. 'www.torre.ai' when only 'torre.ai' is trusted, 'api.torre.co' (old domain), or 'torre.ai.evil.io'.
Common situations: Torre domain migration (torre.co → torre.ai style) leaving old URLs in config; adding/omitting 'www.'; third-party mirrors or job aggregators linking to copies of Torre postings; malicious URLs from untrusted input.
Related errors
- themuse: untrusted hostname "${parsed.hostname}" — must be $
- refusing to archive restricted destination: ${preGuard.reaso
- Invalid or blocked URL: ${rejected.reason}
- Access denied: Localhost or internal domain target detected.
- 4dayweek: untrusted hostname "${parsed.hostname}" — must be
AI-assisted analysis of santifer/career-ops@1696bec4d0 (2026-09-01).
Data as JSON: /api/errors/daf81efe20054a79.
Report an issue: GitHub.